How to render a react-router Link component from text?

Viewed 2438

Here's my situation:

This is a Single Page App that is using react-router-dom to perform client-side routing.

I have a AddBlogPostPage where the admin will create blogPosts.

  • This page has lots of inputs and textareas to build the blogPost paragraphs and images.
  • Inside a textarea input, the admin will enter a paragraph text that will be rendered inside a <p> tag using dangerouslySetInnerHTML when the blogPost is displayed.
  • But sometimes is necessary to add links to other pages of the App and I'm doing the following:
  • The admin enters in the textarea:
    • For example: the text pattern [products](/products)
    • And this gets replaced and rendered as <a href="/products">products</a>

But when I click on the <a> the App refreshes other than switch routes with react-router-dom. That is because I'm using an <a> tag instead of a Link component that comes built-in with react-router-dom.

But since I'm rendering my paragraphs with dangerouslySetInnerHTML, how can I display the React component Link instead of an html tag <a> in this situation?

From my research so far, this does not seem to be possible. Is there any other way around this?

2 Answers

I'm quite sure this isn't the the most efficient way of doing it, nor is it really reuseable. But here is, at least, a starting point.

You're storing that textarea information in state, I assume. When rendering it FROM state, use

const firstText = this.state.userText.split('[products]');

to get everything before your tag, then

const lastText = firstText[1].split('[/products]');

to get everything after your link. Your render will look something like:

<p>
    {firstText[0]}
    <Link to="/products">{lastText[0]}</Link>
    {lastText[1]}
</p>

For an actual use case, you'll want to store that in state, keep track of what & where all of your tags are, and throw everything into an array in a separate state entry so you can map the output appropriately. This would undoubtedly be a method instead of a series of variable declarations. And I'm sure it's not terribly efficient. But it's not impossible!

Best of luck.

You can use this I write for that..

import React from 'react';
import {Link} from 'react-router-dom';
export const addLinkToText = (text) => {
        const sptx= text.split('|');
        const newTxt=sptx.map((txt,indx) => {
            const sptx2= txt.split(':');
            if(sptx2.length>1){
                return <Link key={`lk${indx}`} to={sptx2[1]}>{sptx2[0]}</Link>
            }
            return sptx2[0];
        });
        return newTxt;
}

And then parse text like this:

<div>{addLinkToText("some text |text for link:/path_of_url| more text.")}</div>
Related