Sebastian Olsen Sebastian Olsen - 1 month ago 9
React JSX Question

Replacing characters between strings with html tags in react

I'm trying to parse some text so that

_this is emphasized!_
is wrapped in tags like so:
<em>this is emphasized!</em>
.

My component currently looks like this:

export default class TextParser extends React.Component {
render() {
let text = this.props.text,
parsed, regex, paragraphs;

regex = {
paragraph: /(?:\r\n){2,}/g,
emphasize: /\_(.*?)\_/g,
strong: /\*(.*?)\*/g,
}

// Apply regex
text = text.replace(regex.emphasize, (str) => {
let parsed = str.substr(1, str.length - 1);

return ('<em>' + parsed + '</em>')
})

paragraphs = text.split(regex.paragraph) || []
paragraphs = paragraphs.map((text, i) => {
return (
<p key={i}>
{text}
</p>
)
})

return (
<div className="document">{paragraphs}</div>
)
}
}


This does not work, however the output html displays the tags in plain text instead of using them in the html. This is of course because of sanitization.

I could
dangerouslySetInnerHTML
but I want to avoid that. How can I replace the underscores between text with
<em>
tags?

Answer

As you noticed, placing the string "<em>" as part of the result of replace just adds that string and not an actual tag.

You will not be able create tags directly inside of replace because that is operating on a string.

Instead, break the string up into separate elements and add the tags where you need them. You already do something like this in the paragraph case.

Because the paragraph case also operates on a string, these kind of operations can only be done nested, since once you complete the operation you no longer have a plain text string, you have an array of objects. So in this example I moved the <em> parsing inside the paragraph parsing.

One last note, I had to modify the regex for emphasize so that it captured the underscores, because I need to check again whether it was a match or not after I have done the split.

let text = this.props.text,
    parsed, regex, paragraphs;

regex = {
  paragraph: /(?:\r\n){2,}/g,
  emphasize: /(\_.*?\_)/g,
  strong: /\*(.*?)\*/g,
}

paragraphs = text.split(regex.paragraph) || []
paragraphs = paragraphs.map((text, i) => {
  return (
    <p key={i}>
      {        
           // Apply regex
           text.split(regex.emphasize).map((str) => {
           let parsed = str.search(regex.emphasize) !== -1 
              ? (<em>{str.substr(1, str.length - 2)}</em>) 
              : str;
            return parsed;
        })}
    </p>
  )
})

return (
  <div className="document">{paragraphs}</div>
)
Comments