I'm trying to convert the output from a free text comment field into a formatted component. I have an array of substitution strings which I would like to replace within the text and attach click handlers to as well. I'm struggling to think of a nice way to do it, I don't really want to go down the dangerouslySetInnerHTML route if possible. Here's what I started to work on but didn't get very far with:
const FormattedComment = () => {
const comment = 'Some info about 1A and 2A... maybe 1A again.';
const substitutions = ['1A', '2A', '3A'];
const subPostions: { sub: string; pos: number }[] = [];
for (const sub of substitutions) {
// this won't handle duplicates :(
const pos = comment.indexOf(sub);
if (pos >= 0) {
subPostions.push({ sub, pos });
}
}
// do something here (map? forEach?)
};
In the hope that I could produce something like this (or better):
<>
<span>Some info about </span>
<strong onClick={() => {}}>1A</strong>
<span> and </span>
<strong onClick={() => {}}>2A</strong>
<span>... maybe </span>
<strong onClick={() => {}}>1A</strong>
<span> again.</span>
</>
Any suggestions or working examples would be much appreciated.
You need to use regular expressions for doing this. I created a sandbox for it: https://codesandbox.io/s/intelligent-sea-tfxpk?file=/src/App.js
EDIT:
I updated my solution. It's much simpler now works great. Additionally, it is a better approach from a performance standpoint as it does not create an array from all the words in the string, but only from those that are needed.
let comment = "Some info about 1A and 2A maybe 1A again.";
const substitutions = ["1A", "2A", "3A"];
const parts = comment.split(
new RegExp(
String.raw`(\b${String(substitutions).replaceAll(",", "|")}+\b)`,
"gi"
)
);
for (let i = 1; i < parts.length; i += 2) {
parts[i] = <strong key={i}>{parts[i]}</strong>;
}
return <div className="App">{parts}</div>;
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