Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to combine JSX component with dangerouslySetInnerHTML

I'm displaying text that was stored in the database. The data is coming from firebase as a string (with newline breaks included). To make it display as HTML, I originally did the following:

<p className="term-definition"
        dangerouslySetInnerHTML={{__html: (definition.definition) ? definition.definition.replace(/(?:\r\n|\r|\n)/g, '<br />') : ''}}></p>

This worked great. However there's one additional feature. Users can type [word] and that word will become linked. In order to accomplish this, I created the following function:

  parseDefinitionText(text){
    text = text.replace(/(?:\r\n|\r|\n)/g, '<br />');
    text = text.replace(/\[([A-Za-z0-9'\-\s]+)\]/, function(match, word){
      // Convert it to a permalink
      return (<Link to={'/terms/' + this.permalink(word) + '/1'}>{word}</Link>);
    }.bind(this));
    return text;
  },

I left out the this.permalink method as it's not relevant. As you can see, I'm attempting to return a <Link> component that was imported from react-router.However since it's raw HTML, dangerouslySetInnerHTML no longer works properly.

So I'm kind of stuck at this point. What can I do to both format the inner text and also create a link?

like image 666
Nick ONeill Avatar asked Dec 28 '25 23:12

Nick ONeill


1 Answers

You could split the text into an array of Links + strings like so:

import {Link} from 'react-router';

const paragraphWithLinks = ({markdown}) => {
  const linkRegex = /\[([\w\s-']+)\]/g;

  const children = _.chain(
    markdown.split(linkRegex) // get the text between links
  ).zip(
    markdown.match(linkRegex).map( // get the links
      word => <Link to={`/terms/${permalink(word)}/1`}>{word}</Link> // and convert them
    )
  ).flatten().thru( // merge them
    v => v.slice(0, -1) // remove the last element (undefined b/c arrays are different sizes)
  ).value();

  return <p className='term-definition'>{children}</p>;
};

The best thing about this approach is removing the need to use dangerouslySetInnerHTML. Using it is generally an extremely bad idea as you're potentially creating an XSS vulnerability. That may enable hackers to, for example, steal login credentials from your users.

In most cases you do not need to use dangerouslySetHTML. The obvious exception is for integration w/ a 3rd party library, which should still be considered carefully.

like image 80
Ashton Six Avatar answered Dec 30 '25 12:12

Ashton Six



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!