简体   繁体   中英

Is there a way to manipulate rendered text in react component children?

I am trying to write a component that highlights text inside it's children recursively.

What I have been able to achieve, is to highlight the text only if it's explicitly provided in the body component, but I can't find a way to change the text of the component's render part.

Let's say I have the following HighlightText component:
(Note, that this is a concept component. The real component is much more complicated)

const HighlightText = ({highlight, children}) => {
    const regex = new RegExp(`(${regexEscape(highlight)})`, 'gi');
    return React.Children.map(children, child => {
        // Found a text, can highlight
        if (typeof child === 'string') {
            const text = child.trim();
            if (text) {
                return text.split(regex).filter(p => p).map((p, i) =>
                    regex.test(p) ? <mark key={i}>{p}</mark> : <span>{p}</span>;
                );
            }
        }
        
        // If child is a react component, recurse through its children to find more text to highlight
        if (React.isValidElement(child)) {
            if (child.props && child.props.children) {
                return HighlightText({children: child.props.children, highlight});
            }
        }

        // Here I believe, should be another handling that handles the result of the render function to search for more text to highlight...  

        // For any other cases, leave the child as is.
        return child;
    })
}

And some component that renders something:

const SomeContent = () => <div>content</div>;

Now, I want to use the HighlightText component the following way:

ReactDOM.render(

    <HighlightText highlight="e">
        <SomeContent />
        <p>some paragraph</p>
        nude text
    </HighlightText>

,document.body);

The resulted DOM of the the above code is:

<div>content</div>
<p><span>som</span><mark>e</mark><span> paragraph</span></p>
<span>nud</span><mark>e</mark><span> t</span><mark>e</mark><span>xt</span>

But I expect it to be:

<div><span>cont</span><mark>e</mark><span>nt</span></div>
<p><span>som</span><mark>e</mark><span> paragraph</span></p>
<span>nud</span><mark>e</mark><span> t</span><mark>e</mark><span>xt</span>

Any suggestions on how to handle the rendered part of the child component?

Eventually I managed to solve this problem using React.Context .

Not exactly as I expected, but I think it's even a better approach, because now I can decide what text to highlight.

It's similar to i18n and themes techniques in React. React.Context is best approach for these kind of text manipulations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM