User123123
User123123

Reputation: 573

Replacing custom text with a react component

I'm trying to implement a feature, when a user comments and makes a special reference I want to replace that reference with a react component. Use this as an example:

This is my first post on this app, check out these 2 games @apps_blackjack & @apps_weather.

The keyword to look for in a string is anything that starts with "@apps_" and then get the second keyword "blackjack" or "weather" and returns a component while passing down that variable to the component.

This is what I'm expecting:

<Link className='post_link' to={props.app}>
  Link
</Link>

The {props.app} variable would be blackjack or weather in this case. The final outcome would be:

This is my first post on this app, check out these 2 games 
<Link className='post_link' to='blackjack'>
  Link
</Link>
 & 
<Link className='post_link' to='weather'>
  Link
</Link>

I'm thinking about using string.replace() but am not exactly sure how to implement it as it is much more complicated since we need to also preserve the keyword that comes after the @apps_ keyword.

This is somehow similar to the feature that Facebook uses in the messenger app to highlight user names.

Upvotes: 1

Views: 404

Answers (1)

tenshi
tenshi

Reputation: 26327

You can first split by the mentions, then match the mentions with the same regex. Next, you would "interlace" them together with flatMap. Then you can render the final array of text and elements. Here I've used a regular anchor element that directs you to a Google search of the mention, but the idea should translate to your real code as well.

function App() {
    const text = "This is my first post on this app, check out these 2 games @apps_blackjack & @apps_weather.";
    const mention = /@apps_\w+/g;
    
    const splitted = text.split(mention);
    const mentions = text.match(mention);
    
    const together = splitted.flatMap((text, index) => index < mentions.length ? [text, <a href={`https://www.google.com/search?q=${mentions[index].slice("@apps_".length)}`}>{mentions[index]}</a>] : [text]);
    
    return <div>{together}</div>;
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.0.0/umd/react-dom.production.min.js"></script>
<duv id="root"></div>

Upvotes: 4

Related Questions