Skip to content
Advertisement

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?

Advertisement

Answer

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.

User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement