306

I'm having trouble dealing with facebook's ReactJS. Whenever I do ajax and want to display an html data, ReactJS displays it as text. (See figure below)

ReactJS render string

The data is displayed through the success callback function of the jquery Ajax.

$.ajax({
   url: url here,
   dataType: "json",
   success: function(data) {
      this.setState({
           action: data.action
      })
   }.bind(this)
});

enter image description here

Is there any easy way to convert this into html? How should I do it using ReactJS?

Penny Liu
  • 15,447
  • 5
  • 79
  • 98
Peter Wateber
  • 3,824
  • 4
  • 21
  • 26
  • You can view my answer here - w/o using dangerouslySetInnerHTML https://stackoverflow.com/a/58626638/10816972 – Prakash N Feb 17 '23 at 09:46

12 Answers12

529

By default, React escapes the HTML to prevent XSS (Cross-site scripting). If you really want to render HTML, you can use the dangerouslySetInnerHTML property:

<td dangerouslySetInnerHTML={{__html: this.state.actions}} />

React forces this intentionally-cumbersome syntax so that you don't accidentally render text as HTML and introduce XSS bugs.

Juan Marco
  • 3,081
  • 2
  • 28
  • 32
Sophie Alpert
  • 139,698
  • 36
  • 220
  • 238
  • 6
    This syntax is shown on the homepage and in the tutorial, but I just realized it's not documented anywhere else so I just filed [#413](https://github.com/facebook/react/issues/413) to fix. – Sophie Alpert Oct 09 '13 at 16:34
  • 1
    Correct! I've solved this already using dangerouslySetInnerHTML but thanks though :) – Peter Wateber Oct 10 '13 at 02:37
  • 4
    It's worth playing it safe to sanitize the content using the `sanitize` function from the `dompurify` npm package if you're getting that information from an external API. – Barry Michael Doyle Jan 27 '20 at 08:10
  • 5
    Note that despite it being 'dangerous' if you are merely using it to render html from your server it's no more dangerous than displaying that content in a webpage. The danger arises if that content has user provided input that hasn't been sanitized and if it's direct from the server you should have already sanitized in back end. – Peter Gerdes May 30 '21 at 23:41
  • You can try the easiest solution https://stackoverflow.com/questions/19266197/reactjs-convert-html-string-to-jsx/65022192#65022192 – Sunil Kumar Oct 21 '21 at 17:10
92

There are now safer methods to accomplish this. The docs have been updated with these methods.

Other Methods

  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'}} />

Brett DeWoody
  • 59,771
  • 29
  • 135
  • 184
  • 23
    I've ready the documentation but about a long HTML string such as one from a WYSIWYG editor? I can't see how we can use the 1st, 2nd or 3rd method – ericn Aug 14 '15 at 03:47
  • 5
    I agree with @eric. What good are methods 1-3 for already escaped content stored somewhere, e.g. a DB? Also note that method 4 – the only method – means you can't add child nodes. – dvdplm Sep 23 '15 at 19:20
  • 24
    Yup. These examples with hard-coded "dynamic" content don't make a lot of sense. – regularmike Oct 10 '15 at 00:47
  • This is my innerHTML - "Displaying admins \u003cb\u003e1\u0026nbsp;-\u0026nbsp;10\u003c/b\u003e of \u003cb\u003e13\u003c/b\u003e in total" while this is what is being rendered - "Displaying admins 1 - 10 of 13 in total". When I try to use dangerouslySetInnerHTML, evrything breaks. – Vipin Verma Mar 21 '16 at 11:36
66

I recommend using Interweave created by milesj. Its a phenomenal library that makes use of a number if ingenious techniques to parse and safely insert HTML into the DOM.

Interweave is a react library to safely render HTML, filter attributes, autowrap text with matchers, render emoji characters, and much more.

  • Interweave is a robust React library that can:
    • Safely render HTML without using dangerouslySetInnerHTML.
    • Safely strip HTML tags.
    • Automatic XSS and injection protection.
    • Clean HTML attributes using filters.
    • Interpolate components using matchers.
    • Autolink URLs, IPs, emails, and hashtags.
    • Render Emoji and emoticon characters.
    • And much more!

Usage Example:

import React from 'react';
import { Markup } from 'interweave';

const articleContent = "<p><b>Lorem ipsum dolor laboriosam.</b> </p><p>Facere debitis impedit doloremque eveniet eligendi reiciendis <u>ratione obcaecati repellendus</u> culpa? Blanditiis enim cum tenetur non rem, atque, earum quis, reprehenderit accusantium iure quas beatae.</p><p>Lorem ipsum dolor sit amet <a href='#testLink'>this is a link, click me</a> Sunt ducimus corrupti? Eveniet velit numquam deleniti, delectus  <ol><li>reiciendis ratione obcaecati</li><li>repellendus culpa? Blanditiis enim</li><li>cum tenetur non rem, atque, earum quis,</li></ol>reprehenderit accusantium iure quas beatae.</p>"

<Markup content={articleContent} /> // this will take the articleContent string and convert it to HTML markup. See: https://milesj.gitbook.io/interweave


//to install package using npm, execute the command
npm install interweave
Chukwuemeka Maduekwe
  • 6,687
  • 5
  • 44
  • 67
Arman Nisch
  • 1,132
  • 11
  • 11
30
npm i html-react-parser;

import Parser from 'html-react-parser';

<td>{Parser(this.state.archyves)}</td>
Sophie cai
  • 195
  • 4
  • 13
Donatas Kuskys
  • 301
  • 4
  • 6
  • The latest version of this library provides a very clean way of injecting html. And the `replace` method is a great way to replace (for example) `img` tags with your own `` components. – Micros Dec 16 '20 at 12:54
14

For those still experimenting, npm install react-html-parser

When I installed it it had 123628 weekly downloads.

import ReactHtmlParser from 'react-html-parser'

<div>{ReactHtmlParser(htmlString)}</div>
Unheilig
  • 16,196
  • 193
  • 68
  • 98
13

You can use the following if you want to render raw html in React

<div dangerouslySetInnerHTML={{__html: `html-raw-goes-here`}} />

Example - Render

Test is a good day

Panayiotis Georgiou
  • 1,135
  • 3
  • 19
  • 36
8

This could have been solved by using the content put inside this block {[]} like this. Example could be referred below for better clarity.

{[
   'abc',
   <b>my bold</b>, 
   'some other text'
]} 

This would preserve the formatting for text under tags while the others would be printed as plain text.

Sunil Kumar
  • 388
  • 5
  • 15
6

i found this js fiddle. this works like this

function unescapeHTML(html) {
    var escapeEl = document.createElement('textarea');
    escapeEl.innerHTML = html;
    return escapeEl.textContent;
}

<textarea className="form-control redactor"
                          rows="5" cols="9"
                          defaultValue={unescapeHTML(this.props.destination.description)}
                          name='description'></textarea>

jsfiddle link

Hassan Gilak
  • 691
  • 9
  • 14
5

i start using npm package called react-html-parser

Dayan
  • 711
  • 5
  • 16
  • 27
4

You can also use Parser() from html-react-parser. I have used the same. Link shared.

Abhra Dey
  • 111
  • 1
  • 2
  • 9
4

One option that's missing in the existing answers is using <React.Fragment> (available in React v16 and later). I find this best because this allows you to store any html element as a JSX variable and refer to it later. Also because using dangerouslySetInnerHTML is not secure.

For Example

const App = () => {
    const Windows = <React.Fragment>Microsoft <abbr title="Operating System">OS</abbr></React.Fragment>

    return (
      <ul>
        <li>{Windows}</li>
      </ul>
    );
};

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>

Other alternatives and considerations:

  1. If you're fetching the HTML from external sources, then you cannot use this approach because the fetched HTML will be in a string format. In that case you need to parse the HTML using a HTML Parser like html-react-parser
  2. If you don't have any keys or attributes, you can also use <></> which is a shorthand for <React.Fragment></React.Fragment>
  3. Keep in mind that dangerouslySetInnerHTML is dangerous to use because malicious client side code can be injected via script tags:
  4. @Brett has also suggested other alternatives:
  5. Note: using quotes in a JSX Variale
    • You should not surround a JSX variable with quotes (like a regular variable) - you should surround it with <React.Fragment> </ React.Fragment>
    • you should not escape quotes in a html tag of a JSX variable - for example the title in <abbr /> tag above has quotes which are not escaped.
Gangula
  • 5,193
  • 4
  • 30
  • 59
  • 1
    const samplehtml = "

    Microsoft OS

    " const Windows = {samplehtml} This is not working
    – sai vineeth Dec 20 '21 at 09:26
  • even `samplehtml` is a JSX variable, so you need to enclose that with `` as well - like this: `const samplehtml =

    Microsoft OS

    `
    – Gangula Dec 20 '21 at 10:03
  • I made suggested changes but still html is rendered as string – sai vineeth Dec 20 '21 at 10:07
  • you probably have a syntax error. You should not surround a JSX variable with quotes and you should not escape quotes in your`` tag as well. Copy the `samplehtml` variable from above comment. – Gangula Dec 20 '21 at 10:30
  • samplehtml is html coming from database so it is surrounded by quotes I want convert htmlstring coming from database to jsx – sai vineeth Dec 20 '21 at 12:05
  • Try this answer: https://stackoverflow.com/a/49323189/6908282 – Gangula Dec 20 '21 at 14:02
  • Actually, your use case needs a different approach - since you're fetching the HTML from a database, you need to parse it either using a [HTML Parser](https://stackoverflow.com/a/45617112/6908282) or use `dangerouslySetInnerHTML` – Gangula Dec 20 '21 at 14:10
  • Actually I didn't want use other libraries , Using react API is there any way to parse html string to React JSX? – sai vineeth Dec 20 '21 at 14:43
  • dangerouslySetInnerHTML is danger so thats my last resort – sai vineeth Dec 20 '21 at 14:45
  • I am getting Blog content from Database putting it inside span may effect SEO – sai vineeth Dec 20 '21 at 14:46
  • I'm afraid I'm not aware of any other way. Also you have concerns are not exactly related to this question. So I suggest you to post a new question mentioning all you concerns which would get the right folks to provide you an answer. – Gangula Dec 20 '21 at 14:50
  • Actually I am in correct question- [ReactJS convert HTML string to JSX](https://stackoverflow.com/questions/19266197/reactjs-convert-html-string-to-jsx), that is what I want converting html in string to JSX – sai vineeth Dec 21 '21 at 03:42
0

If you know ahead what tags are in the string you want to render; this could be for example if only certain tags are allowed in the moment of the creation of the string; a possible way to address this is use the Trans utility:

import { Trans } from 'react-i18next'
import React, { FunctionComponent } from "react";

export type MyComponentProps = {
    htmlString: string
}

export const MyComponent: FunctionComponent<MyComponentProps> = ({
  htmlString
}) => {
  return (
    <div>
      <Trans
        components={{
          b: <b />,
          p: <p />
        }}
      >
        {htmlString}
      </Trans>
    </div>
  )
}

then you can use it as always

<MyComponent
    htmlString={'<p>Hello <b>World</b></p>'}
/>
Alejandro
  • 51
  • 6