reactjsnext.jsnext-linkreact-link

How to wrap hashtag and @username with next Link?


I am working on an application where users can create posts and can mention other users and use the #hashtag in the post. Through API call I get the list of post, now the question is how can we wrap hashtags and usernames with next.js Link component so that on clicking on these link user can be navigated to different pages without page refresh.

I am able to wrap this with <a> tag and render the text with dangerouslySetInnerHTML. But this way my page will get refreshed by clicking on the link I don't want off course this behavior.

Here's my code to format the text with <a> tag:

export const formatPostText = (text) => {
    let splitText = text.split(' ')
    splitText.forEach((word, index) => {
        if (word[0] === "@") {
            splitText[index] = '<a class="text-cyanBlue" href="/' + word.replace('@', '') + '/in' + '">' + word + '</a>'
        } else if (word[0] === "#") {
            splitText[index] = '<a class="text-cyanBlue" href="hashtag' + '/' + word.replace('#', '') + '">' + word + '</a>'
        }
    })
    return splitText.join(' ')
}

I do want the same behavior as LinkedIn and Facebook has done it.

Approach: One way I can think of is to use React.createElement but I doubt this is gonna work.

Thanks in advance!!


Solution

  • I implemented similar things in a recent project. I hope this might be helpful.

    export const formatText = (text) => {
        console.log("text", text)
        let content = text.split(/((?:#|@|https?:\/\/[^\s]+)[a-zA-Z]+)/);
        let hashtag;
        let username;
        return content.map((word) => {
            if (word.startsWith("#")) {
                hashtag = word.replace('#', '')
                return <Link href={`/hashtag/${hashtag}`}><a
                    className="text-cyanBlue/80 hover:text-cyanBlue">{word}</a></Link>;
            } else if (word.startsWith("@")) {
                username = word.replace('@', '')
                return <Link href={`/profile/${username}`}><a
                    className="text-cyanBlue/80 hover:text-cyanBlue">{word}</a></Link>;
            } else if (word.includes("http")) {
                return <a target="_blank" href={word} className="text-cyanBlue/80 hover:text-cyanBlue">{word}</a>
            } else {
                return word;
            }
        });
    }