Here's what I tried and how it goes wrong.
This works:
<div dangerouslySetInnerHTML={{ __html: "<h1>Hi there!</h1>" }} />
This doesn't:
<div dangerouslySetInnerHTML={{ __html: this.props.match.description }} />
The description property is just a normal string of HTML content. However it's rendered as a string, not as HTML for some reason.
Any suggestions?
This question is related to
javascript
html
reactjs
jsx
In my case, I used react-render-html
First install the package by npm i --save react-render-html
then,
import renderHTML from 'react-render-html';
renderHTML("<a class='github' href='https://github.com'><b>GitHub</b></a>")
i use https://www.npmjs.com/package/html-to-react
const HtmlToReactParser = require('html-to-react').Parser;
let htmlInput = html.template;
let htmlToReactParser = new HtmlToReactParser();
let reactElement = htmlToReactParser.parse(htmlInput);
return(<div>{reactElement}</div>)
dangerouslySetInnerHTML
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. So, you can set HTML directly from React, but you have to type out dangerouslySetInnerHTML and pass an object with a __html key, to remind yourself that it’s dangerous. For example:
function createMarkup() {
return {__html: 'First · Second'};
}
function MyComponent() {
return <div dangerouslySetInnerHTML={createMarkup()} />;
}
I use innerHTML together a ref to span:
import React, { useRef, useEffect, useState } from 'react';
export default function Sample() {
const spanRef = useRef<HTMLSpanElement>(null);
const [someHTML,] = useState("some <b>bold</b>");
useEffect(() => {
if (spanRef.current) {
spanRef.current.innerHTML = someHTML;
}
}, [spanRef.current, someHTML]);
return <div>
my custom text follows<br />
<span ref={spanRef} />
</div>
}
I use 'react-html-parser'
yarn add react-html-parser
import ReactHtmlParser from 'react-html-parser';
<div> { ReactHtmlParser (html_string) } </div>
Source on npmjs.com
Lifting up @okram's comment for more visibility:
from its github description: Converts HTML strings directly into React components avoiding the need to use dangerouslySetInnerHTML from npmjs.com A utility for converting HTML strings into React components. Avoids the use of dangerouslySetInnerHTML and converts standard HTML elements, attributes and inline styles into their React equivalents.
I could not get npm build
to work with react-html-parser
. However, in my case, I was able to successfully make use of https://reactjs.org/docs/fragments.html. I had a requirement to show few html unicode characters , but they should not be directly embedded in the JSX. Within the JSX, it had to be picked from the Component's state. Component code snippet is given below :
constructor()
{
this.state = {
rankMap : {"5" : <Fragment>★ ★ ★ ★ ★</Fragment> ,
"4" : <Fragment>★ ★ ★ ★ ☆</Fragment>,
"3" : <Fragment>★ ★ ★ ☆ ☆</Fragment> ,
"2" : <Fragment>★ ★ ☆ ☆ ☆</Fragment>,
"1" : <Fragment>★ ☆ ☆ ☆ ☆</Fragment>}
};
}
render()
{
return (<div class="card-footer">
<small class="text-muted">{ this.state.rankMap["5"] }</small>
</div>);
}
If you have control to the {this.props.match.description} and if you are using JSX. I would recommend not to use "dangerouslySetInnerHTML".
// In JSX, you can define a html object rather than a string to contain raw HTML
let description = <h1>Hi there!</h1>;
// Here is how you print
return (
{description}
);
If you have HTML in a string, I would recommend using a package called html-react-parser
.
Install it: npm install html-react-parser
or if you use yarn, yarn add html-react-parser
Use it something like this
import parse from 'html-react-parser'
const yourHtmlString = '<h1>Hello</h1>'
<div>
{parse(yourHtmlString)}
</div>
If you have control over where the string containing html is coming from (ie. somewhere in your app), you can benefit from the new <Fragment>
API, doing something like:
import React, {Fragment} from 'react'
const stringsSomeWithHtml = {
testOne: (
<Fragment>
Some text <strong>wrapped with strong</strong>
</Fragment>
),
testTwo: `This is just a plain string, but it'll print fine too`,
}
...
render() {
return <div>{stringsSomeWithHtml[prop.key]}</div>
}
You can also use parseReactHTMLComponent from Jumper Package. Just look at it, it's easy and you don't need to use JSX syntax.
https://codesandbox.io/s/jumper-module-react-simple-parser-3b8c9?file=/src/App.js .
More on Jumper:
https://github.com/Grano22/jumper/blob/master/components.js
NPM Package:
Is this.props.match.description
a string or an object? If it's a string, it should be converted to HTML just fine. Example:
class App extends React.Component {
constructor() {
super();
this.state = {
description: '<h1 style="color:red;">something</h1>'
}
}
render() {
return (
<div dangerouslySetInnerHTML={{ __html: this.state.description }} />
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
Result: http://codepen.io/ilanus/pen/QKgoLA?editors=1011
However if description is <h1 style="color:red;">something</h1>
without the quotes ''
, you're going to get:
?Object {
$$typeof: [object Symbol] {},
_owner: null,
key: null,
props: Object {
children: "something",
style: "color:red;"
},
ref: null,
type: "h1"
}
If It's a string and you don't see any HTML markup the only problem I see is wrong markup..
UPDATE
If you are dealing with HTML Entities, You need to decode them before sending them to dangerouslySetInnerHTML
that's why it's called "dangerously" :)
Working example:
class App extends React.Component {
constructor() {
super();
this.state = {
description: '<p><strong>Our Opportunity:</strong></p>'
}
}
htmlDecode(input){
var e = document.createElement('div');
e.innerHTML = input;
return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
}
render() {
return (
<div dangerouslySetInnerHTML={{ __html: this.htmlDecode(this.state.description) }} />
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
You just use dangerouslySetInnerHTML method of React
<div dangerouslySetInnerHTML={{ __html: htmlString }} />
Or you can implement more with this easy way: Render the HTML raw in React app
Source: Stackoverflow.com