Rendering raw html with reactjs

JavascriptReactjs

Javascript Problem Overview


So is this the only way to render raw html with reactjs?

// http://facebook.github.io/react/docs/tutorial.html
// tutorial7.js
var converter = new Showdown.converter();
var Comment = React.createClass({
  render: function() {
    var rawMarkup = converter.makeHtml(this.props.children.toString());
    return (
      <div className="comment">
        <h2 className="commentAuthor">
          {this.props.author}
        </h2>
        <span dangerouslySetInnerHTML={{__html: rawMarkup}} />
      </div>
    );
  }
});

I know there are some cool ways to markup stuff with JSX, but I am mainly interested in being able to render raw html (with all the classes, inline styles, etc..). Something complicated like this:

<!-- http://getbootstrap.com/components/#dropdowns-example -->
<div class="dropdown">
  <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-expanded="true">
    Dropdown
    <span class="caret"></span>
  </button>
  <ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Action</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Another action</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Something else here</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Separated link</a></li>
  </ul>
</div>

I would not want to have to rewrite all of that in JSX.

Maybe I am thinking about this all wrong. Please correct me.

Javascript Solutions


Solution 1 - Javascript

There are now safer methods to render HTML. I covered this in a previous answer here. You have 4 options, the last uses dangerouslySetInnerHTML.

Methods for rendering HTML

  1. Easiest - Use Unicode, save the file as UTF-8 and set the charset to UTF-8.

    <div>{'First · Second'}</div>

  2. Safer - Use the Unicode number for the entity inside a Javascript string.

    <div>{'First \u00b7 Second'}</div>

or

`<div>{'First ' + String.fromCharCode(183) + ' Second'}</div>`

3. Or a mixed array with strings and JSX elements.

`<div>{['First ', <span>&middot;</span>, ' Second']}</div>`

4. Last Resort - Insert raw HTML using dangerouslySetInnerHTML.

`<div dangerouslySetInnerHTML={{__html: 'First &middot; Second'}} />`

Solution 2 - Javascript

You could leverage the html-to-react npm module.

Note: I'm the author of the module and just published it a few hours ago. Please feel free to report any bugs or usability issues.

Solution 3 - Javascript

dangerouslySetInnerHTML is React’s replacement for using innerHTML in the browser DOM. In general, setting HTML from code is risky because it’s easy to inadvertently expose your users to a cross-site scripting (XSS) attack.

It is better/safer to sanitise your raw HTML (using e.g., DOMPurify) before injecting it into the DOM via dangerouslySetInnerHTML.

DOMPurify - a DOM-only, super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG. DOMPurify works with a secure default, but offers a lot of configurability and hooks.

Example:

import React from 'react'
import createDOMPurify from 'dompurify'
import { JSDOM } from 'jsdom'

const window = (new JSDOM('')).window
const DOMPurify = createDOMPurify(window)

const rawHTML = `
<div class="dropdown">
  <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-expanded="true">
    Dropdown
    <span class="caret"></span>
  </button>
  <ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Action</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Another action</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Something else here</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#">Separated link</a></li>
  </ul>
</div>
`

const YourComponent = () => (
  <div>
    { <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(rawHTML) }} /> }
  </div>
)

export default YourComponent

Solution 4 - Javascript

I have used this in quick and dirty situations:

// react render method:

render() {
    return (
      <div>
        { this.props.textOrHtml.indexOf('</') !== -1
            ? (
                <div dangerouslySetInnerHTML={{__html: this.props.textOrHtml.replace(/(<? *script)/gi, 'illegalscript')}} >
                </div>
              )
            : this.props.textOrHtml
          }

      </div>
      )
  }

Solution 5 - Javascript

I have tried this pure component:

const RawHTML = ({children, className = ""}) => 
<div className={className}
  dangerouslySetInnerHTML={{ __html: children.replace(/\n/g, '<br />')}} />

Features

  • Takes classNameprop (easier to style it)
  • Replaces \n to <br /> (you often want to do that)
  • Place content as children when using the component like:
  • <RawHTML>{myHTML}</RawHTML>

I have placed the component in a Gist at Github: RawHTML: ReactJS pure component to render HTML

Solution 6 - Javascript

export class ModalBody extends Component{
    rawMarkup(){
        var rawMarkup = this.props.content
        return { __html: rawMarkup };
    }
    render(){
        return(
                <div className="modal-body">
                     <span dangerouslySetInnerHTML={this.rawMarkup()} />
            
                </div>
            )
    }
}

Solution 7 - Javascript

I used this library called Parser. It worked for what I needed.

import React, { Component } from 'react';    
import Parser from 'html-react-parser';

class MyComponent extends Component {
  render() {
    <div>{Parser(this.state.message)}</div>
  }
};

Solution 8 - Javascript

dangerouslySetInnerHTML should not be used unless absolutely necessary. According to the docs, "This is mainly for cooperating with DOM string manipulation libraries". When you use it, you're giving up the benefit of React's DOM management.

In your case, it is pretty straightforward to convert to valid JSX syntax; just change class attributes to className. Or, as mentioned in the comments above, you can use the ReactBootstrap library which encapsulates Bootstrap elements into React components.

Solution 9 - Javascript

Here's a little less opinionated version of the RawHTML function posted before. It lets you:

  • configure the tag
  • optionally replace newlines to <br />'s
  • pass extra props that RawHTML will pass to the created element
  • supply an empty string (RawHTML></RawHTML>)

Here's the component:

const RawHTML = ({ children, tag = 'div', nl2br = true, ...rest }) =>
    React.createElement(tag, {
        dangerouslySetInnerHTML: {
            __html: nl2br
                ? children && children.replace(/\n/g, '<br />')
                : children,
        },
        ...rest,
    });
RawHTML.propTypes = {
    children: PropTypes.string,
    nl2br: PropTypes.bool,
    tag: PropTypes.string,
};

Usage:

<RawHTML>{'First &middot; Second'}</RawHTML>
<RawHTML tag="h2">{'First &middot; Second'}</RawHTML>
<RawHTML tag="h2" className="test">{'First &middot; Second'}</RawHTML>
<RawHTML>{'first line\nsecond line'}</RawHTML>
<RawHTML nl2br={false}>{'first line\nsecond line'}</RawHTML>
<RawHTML></RawHTML>

Output:

<div>First · Second</div>
<h2>First · Second</h2>
<h2 class="test">First · Second</h2>
<div>first line<br>second line</div>
<div>first line
second line</div>
<div></div>

It will break on:

<RawHTML><h1>First &middot; Second</h1></RawHTML>

Solution 10 - Javascript

I needed to use a link with onLoad attribute in my head where div is not allowed so this caused me significant pain. My current workaround is to close the original script tag, do what I need to do, then open script tag (to be closed by the original). Hope this might help someone who has absolutely no other choice:

<script dangerouslySetInnerHTML={{ __html: `</script>
   <link rel="preload" href="https://fonts.googleapis.com/css?family=Open+Sans" as="style" onLoad="this.onload=null;this.rel='stylesheet'" crossOrigin="anonymous"/>
<script>`,}}/>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionvinhboyView Question on Stackoverflow
Solution 1 - JavascriptBrett DeWoodyView Answer on Stackoverflow
Solution 2 - JavascriptMike NiklesView Answer on Stackoverflow
Solution 3 - JavascriptYuciView Answer on Stackoverflow
Solution 4 - JavascriptCory RobinsonView Answer on Stackoverflow
Solution 5 - JavascriptNetsi1964View Answer on Stackoverflow
Solution 6 - JavascriptJozcarView Answer on Stackoverflow
Solution 7 - JavascriptecairolView Answer on Stackoverflow
Solution 8 - JavascriptBreno FerreiraView Answer on Stackoverflow
Solution 9 - JavascriptChristiaan WesterbeekView Answer on Stackoverflow
Solution 10 - JavascriptAdam LaneView Answer on Stackoverflow