2

I have a React class and the render function works fine. The <li> tag and the internal <a> tag render.
However, the string of HTML returned by getListItem does not render. Instead, it shows up as code on the page, as if it had been escaped.
How do I prevent this behavior in React so I can build dynamic HTML when creating components, as in the (attempted) example below?

class ExchangeListItem extends Component {
  constructor(props) {
    super(props);
  this.state = {
    };
  }

  getListItem() {
    const retStr = '<a className="nav-link active" href="'+this.props.exchange.url+'">'+this.props.exchange.name + '</a>';
    return retStr;
  }

  render() {
    return (
      <li>
        <a href="https://wwww.google.com">Link</a>
        {this.getListItem()}
      </li>
    );
  }
}

At issue here is specifically how React renders something. If it is a string, it will escape the special characters and cause (in this case) HTML to become displayed text. The other post is only asking about how to change innerHTML. In my case, I am not attempting to change an element but trying to get React to render what I intend in the first place.

marcus
  • 77
  • 1
  • 9
  • 2
    Yes, because that's a string not JSX – jonrsharpe May 26 '18 at 13:52
  • While your question is not _exactly_ a duplicate, you'll find the answer at this question https://stackoverflow.com/questions/37337289/react-js-set-innerhtml-vs-dangerouslysetinnerhtml (basically, you are looking for `dangerouslysetInnerHTML`) – John Weisz May 26 '18 at 13:56
  • Thank you John but I think approaching this from the perspective of rendering a react component instead of HTML is the best answer. At issue is not whether I can affect the desired content, but simply what React does with it (it escapes HTML found in strings rather than render it) so providing it with a React object solves that nicely. – marcus May 26 '18 at 15:39

2 Answers2

3

Another cleaner way of doing this in ES6 without the parser is;

import React from 'react';

class ExchangeListItem extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  getListItem = (exchangeUrl, exchangeName) => (
    <a className="nav-link active" href={exchangeUrl}>
      {exchangeName}
    </a>
  );

  render() {
    return (
      <li>
        <a href="https://wwww.google.com">Link</a>
        {this.getListItem(this.props.exchange.url, this.props.exchange.name)}
      </li>
    );
  }
}
  • This worked well and I was able to remove the modules listed below (react-html-parser and json-loader) – marcus May 26 '18 at 20:25
2

I always use react-html-parser to render html content in a component.

Import the parser

import ReactHtmlParser from 'react-html-parser';

Use it in your getListItem method as follows

getListItem() {
  const retStr = '<a className="nav-link active" href="'+this.props.exchange.url+'">'+this.props.exchange.name + '</a>';
  return ReactHtmlParser(retStr);
}

Edit:

Note that react-html-parser is to parse html string that is already stored in an variable. For the above case, where the html string is constructed in the previous line, we could just return the tag in jsx format like any react component.

Dinesh Pandiyan
  • 5,814
  • 2
  • 30
  • 49
  • Thank you so much this is perfect! – marcus May 26 '18 at 15:36
  • For posterity, I would like to add that adding react-html-parser then also required json-loader because I also am using webpack version <2.0. After v 2.0 you don't need json-loader anymore. json-loader also requires a config to tell it to use the loader for .json files. – marcus May 26 '18 at 19:31