I have array of values
const tags = ['Hello', 'moment', 'somewhere'];
and the paragraphs to show in my react component
const paras = [{
text: 'Hello, tina. Thank you for all waiting. Hello?'
}, {
text: 'When can I go? Okay. One moment. Let me just'
}, {
text: 'if I can help you somewhere, if you are interested'
}]

I want to highlight the para words with the tags element. And also only need few words before and after highlighted words like in the first sentence I only need to show like
*One **moment**. Let *
How can I do that?
What I have tried:
getHighlightedText(text, highlight) {
// Split text on highlight term, include term itself into parts, ignore case
const parts = text.split(new RegExp(`(${highlight})`, 'gi'));
return <span>{parts.map(part => part.toLowerCase() === highlight.toLowerCase() ? <span className="highlight">{part}</span> : part)}</span>;
}
{
paras.map((para) => {
return (
<Row key={para._id}>
<Col md={11}>
<div className="record">
<p className="mb-0">
{this.getHighlightedText(para.text, "hello")}
</p>
</div>
</Col>
<Col md={1}>
<Button className="buttonLink" color="link">
<b>{"View >"}</b>
</Button>
</Col>
</Row>
);
});
}
Here is a super simple to use reusable component for text highlighting by tags:
function Highlight({ children: text = "", tags = [] }) {
if (!tags?.length) return text;
const matches = [...text.matchAll(new RegExp(tags.join("|"), "ig"))];
const startText = text.slice(0, matches[0]?.index);
return (
<span>
{startText}
{matches.map((match, i) => {
const startIndex = match.index;
const currentText = match[0];
const endIndex = startIndex + currentText.length;
const nextIndex = matches[i + 1]?.index;
const untilNextText = text.slice(endIndex, nextIndex);
return (
<span key={i}>
<mark>{currentText}</mark>
{untilNextText}
</span>
);
})}
</span>
);
}
export default function App() {
return (
<div className="App">
<h1>
<Highlight tags={["Hel", "co", "nd"]}>Hello CodeSandbox</Highlight>
</h1>
<h2>
<Highlight tags={["ditin", "e"]}>
Start editing to see some magic happen!
</Highlight>
</h2>
</div>
);
}
Demo in Codesndbox

Using it with your example:
const tags = ["Hello", "moment", "somewhere"];
const paras = [
{
text: "Hello, tina. Thank you for all waiting. Hello?"
},
{
text: "When can I go? Okay. One moment. Let me just"
},
{
text: "if I can help you somewhere, if you are interested"
}
];
function ParasList() {
return (
<ul>
{paras.map((para, i) => (
<li key={i}>
<Highlight tags={tags}>{para.text}</Highlight>
</li>
))}
</ul>
);
}

Explanation:
The Highlight component is easy to use, you just wrap around some text, and put on the "tags" attribute: <Highlight tags={["some"]}>some text</Highlight>
Inside the component, I'm using the new and shiny string.prototype.matchAll function, which gives us information about the match and the index where it was found.
Also, I'm creating the regex using join("|") on the tags, so they have an "OR" relationship between them. The flag i makes the highlight case insensitive, but you could delete it if you would want to keep case sensitivity. The g flag is the global flag, so duplicate matches are found and highlighted. It is required in a matchAll search.
Lastly, I'm using the <mark> html tags for highlighting, but you could easily change this, or even pass a custom tag through props for more versatility. You could also just enclose the "marked" bits with a regular span, and mark them with a "highlighted" className, and customize the appearance that way, using CSS.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With