317

I am building something with React where I need to insert HTML with React Variables in JSX. Is there a way to have a variable like so:

var thisIsMyCopy = '<p>copy copy copy <strong>strong copy</strong></p>';

and to insert it into react like so, and have it work?

render: function() {
    return (
        <div className="content">{thisIsMyCopy}</div>
    );
}

and have it insert the HTML as expected? I haven't seen or heard anything about a react function that could do this inline, or a method of parsing things that would allow this to work.

VLAZ
  • 26,331
  • 9
  • 49
  • 67
Kyle Hotchkiss
  • 10,754
  • 20
  • 56
  • 82

10 Answers10

426

You can use dangerouslySetInnerHTML, e.g.

render: function() {
    return (
        <div className="content" dangerouslySetInnerHTML={{__html: thisIsMyCopy}}></div>
    );
}
Community
  • 1
  • 1
Douglas
  • 36,802
  • 9
  • 76
  • 89
151

Note that dangerouslySetInnerHTML can be dangerous if you do not know what is in the HTML string you are injecting. This is because malicious client side code can be injected via script tags.

It is probably a good idea to sanitize the HTML string via a utility such as DOMPurify if you are not 100% sure the HTML you are rendering is XSS (cross-site scripting) safe.

Example:

import DOMPurify from 'dompurify'

const thisIsMyCopy = '<p>copy copy copy <strong>strong copy</strong></p>';


render: function() {
    return (
        <div className="content" dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(thisIsMyCopy)}}></div>
    );
}
Twitter khuong291
  • 11,328
  • 15
  • 80
  • 116
Yo Wakita
  • 5,322
  • 3
  • 24
  • 36
73

dangerouslySetInnerHTML has many disadvantage because it set inside the tag.

I suggest you to use some react wrapper like i found one here on npm for this purpose. html-react-parser does the same job.

import Parser from 'html-react-parser';
var thisIsMyCopy = '<p>copy copy copy <strong>strong copy</strong></p>';


render: function() {
    return (
        <div className="content">{Parser(thisIsMyCopy)}</div>
    );
}

Very Simple :)

UPDATE

in the latest version as usage explained:

// ES Modules
import parse from 'html-react-parser';

// CommonJS
const parse = require('html-react-parser');
....

//Parse single element
parse('<li>Item 1</li><li>Item 2</li>');

//Parse multiple elements
parse('<li>Item 1</li><li>Item 2</li>');
0xFK
  • 2,433
  • 32
  • 24
user2903536
  • 1,716
  • 18
  • 25
  • 4
    "dangerouslySetInnerHTML has many disadvantage because it set inside the tag." Can you explain more about this. Trying to think out what fundamental difference there is between html-react-parser and sanatized innerHtml – dchhetri Mar 29 '18 at 14:55
  • 4
    It seems that html-react-parser doesn't sanitize the input - see the FAQ – Little Brain Dec 03 '19 at 14:50
62

By using '' you are making it to a string. Use without inverted commas it will work fine.

const App = () => {
const span = <span> whatever your string </span>

const dynamicString = "Hehe";
const dynamicStringSpan = <span> {`${dynamicString}`} </span>

  return (
    <div>

      {span}

      {dynamicStringSpan}

    </div>
  );

};

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Gangula
  • 5,193
  • 4
  • 30
  • 59
Amit Chauhan
  • 1,810
  • 3
  • 17
  • 25
  • 4
    By far the simplest answer especially if the HTML is written by you and dynamic based on user input. You can quite literally set var myHtml =

    Some text

    ; and it works
    – pat8719 May 15 '19 at 13:45
  • 3
    I thought it would be for a dynamically generated string (e.g. from user generated content) where your solution would not work. But thanks! – checklist Mar 04 '21 at 17:59
9
import { Fragment } from 'react' // react version > 16.0

var thisIsMyCopy = (
  <Fragment>
    <p>copy copy copy&nbsp;
    <strong>strong copy</strong>
    </p>
  </Fragment>
)

By using '' the sets the value to a string and React has no way of knowing that it is a HTML element. You can do the following to let React know it is a HTML element -

  1. Remove the '' and it would work
  2. Use <Fragment> to return a HTML element.
  • 4
    This does not answer the question. The content of ``thisIsMyCopy`` is itself JSX, not a string of HTML. So you're literally pasting JSX into JSX. – Antares42 Apr 10 '19 at 20:12
  • You can find Fragments in the Preact too but only in version X and on. – Nasia Makrygianni Sep 18 '19 at 08:28
  • I think this is the best way because we don't have to store it as a string variable with this approach. Also keep in mind that `dangerouslySetInnerHTML` is dangerous to use because malicious client side code can be injected via script tags: https://stackoverflow.com/a/42380982/6908282 – Gangula Nov 01 '21 at 21:08
8

To avoid linter errors, I use it like this:

  render() {
    const props = {
      dangerouslySetInnerHTML: { __html: '<br/>' },
    };
    return (
        <div {...props}></div>
    );
  }
Tudor Morar
  • 3,720
  • 2
  • 27
  • 25
6

You don't need any special library or "dangerous" attribute. You can just use React Refs to manipulate the DOM:

class MyComponent extends React.Component {
    
    constructor(props) {
        
        super(props);       
        this.divRef = React.createRef();
        this.myHTML = "<p>Hello World!</p>"
    }
    
    componentDidMount() {
        
        this.divRef.current.innerHTML = this.myHTML;
    }
    
    render() {
        
        return (
            
            <div ref={this.divRef}></div>
        );
    }
}

A working sample can be found here:

https://codepen.io/bemipefe/pen/mdEjaMK

Bemipefe
  • 1,397
  • 4
  • 17
  • 30
  • Good one, and you can even use `this.divRef.current.outerHTML = this.myHTML;` to avoid the extra `div`. However, `createRef` requires React 16.3, that is not always an option, for instance with SPFx for SharePoint 2019 on-prem... – Evariste Mar 18 '21 at 19:51
1

Try Fragment, if you don't want any of above.

In your case, we can write

import React, {useState, Fragment} from 'react'

const thisIsMyCopy = Fragment('<p>copy copy copy <strong>strong copy</strong></p>')

render: function() {
    return (
        <div className="content">{thisIsMyCopy}</div>
    );
}

If you using hook want to set it in a state somewhere with any condition

const [thisIsMyCopy, setThisIsMyCopy] = useState(<Fragment><p>copy copy copy <strong>strong copy</strong></p></Fragment>);
Gangula
  • 5,193
  • 4
  • 30
  • 59
Adarsh Pawar
  • 682
  • 6
  • 15
  • 4
    The library you are referencing is not part of React, but in your code you're importing Fragment from React. Your snippet throws an error. – dols3m Oct 15 '20 at 02:42
  • 1
    the link you provided shows that it is fragment with a lowercase f and does not show where you are importing it from. – bcstryker Feb 10 '22 at 19:59
-3

If anyone else still lands here. With ES6 you can create your html variable like so:

render(){
    var thisIsMyCopy = (
        <p>copy copy copy <strong>strong copy</strong></p>
    );
    return(
        <div>
            {thisIsMyCopy}
        </div>
    )
}
Harry
  • 105
  • 2
  • 2
    and if you want variables inside your string, you'll need to wrap each in `{}` and the whole string in some markup like so `({telephoneNumber}
    {email}
    )`
    – DanV Nov 29 '17 at 09:16
  • 3
    This is different from what's asked in the question. In the question `

    copy copy copy strong copy

    ` is a string. You have it as JSX.
    – YPCrumble Dec 06 '17 at 21:06
  • 5
    That is not ES6, but JSX – gztomas Jan 24 '18 at 23:05
-6

You can also include this HTML in ReactDOM like this:

var thisIsMyCopy = (<p>copy copy copy <strong>strong copy</strong></p>);

ReactDOM.render(<div className="content">{thisIsMyCopy}</div>, document.getElementById('app'));

Here are two links link and link2 from React documentation which could be helpful.

GrassLand
  • 5
  • 2