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.