This question already has answers here:
ReactJS convert HTML string to JSX
(12 answers)
Closed 2 years ago.
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.
You can use dangerouslySetInnerHTML, e.g.
render: function() {
return (
<div className="content" dangerouslySetInnerHTML={{__html: thisIsMyCopy}}></div>
);
}
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>
);
}
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>');
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>
import { Fragment } from 'react' // react version > 16.0
var thisIsMyCopy = (
<Fragment>
<p>copy copy copy
<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 -
Remove the '' and it would work
Use <Fragment> to return a HTML element.
To avoid linter errors, I use it like this:
render() {
const props = {
dangerouslySetInnerHTML: { __html: '<br/>' },
};
return (
<div {...props}></div>
);
}
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
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>);
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>
)
}
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.
Related
This question already has answers here:
ReactJS convert HTML string to JSX
(12 answers)
Closed 2 years ago.
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.
You can use dangerouslySetInnerHTML, e.g.
render: function() {
return (
<div className="content" dangerouslySetInnerHTML={{__html: thisIsMyCopy}}></div>
);
}
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>
);
}
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>');
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>
import { Fragment } from 'react' // react version > 16.0
var thisIsMyCopy = (
<Fragment>
<p>copy copy copy
<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 -
Remove the '' and it would work
Use <Fragment> to return a HTML element.
To avoid linter errors, I use it like this:
render() {
const props = {
dangerouslySetInnerHTML: { __html: '<br/>' },
};
return (
<div {...props}></div>
);
}
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
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>);
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>
)
}
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.
I have a tree structure with a root "Tree" component that has a list of root "TreeNodes", then TreeNodes can have an arbitrary number of children.
So inside of the TreeNode render method I have
childrenHTML = this.state.children.map((child) => {
return (<TreeNode nodeClick ={this.props.nodeClick} parentNode={this}
key={child.childId} node={child} level={this.state.level+1} />);
});
and
const { isDragging, connectDragSource, connectDragPreview} = this.props;
Then the final return for the render method looks like
return connectDragSource(
<div>
<div style={nodeStyle}>
{connectDragPreview(
<div className = {"nodeContainer" + ' ' + this.state.nodeHover} onMouseLeave={this.nodeUnHover} onMouseOver={this.nodeHover} onClick={()=>this.props.nodeClick(this)}>
<img alt = {this.state.titleIcon} className = "titleIcon" src = {Connections.getImageURLByName(this.state.titleIcon)} />
<p className="nodeLabel"> {this.state.nodeName}</p>
{nodeLabelsHTML}
<DescriptiveIcons descriptiveIcons={this.state.icons} />
</div>
)}
</div>
{childrenHTML}
</div>
);
I am exporting:
export default DragSource(DragTypes.STRUCTURE, treeNodeSource, collect)(TreeNode);
Then in the parent Tree file I am exporting
export default DragDropContext(HTML5Backend)(Tree)
and rendering the rootnodes like
rootNodesHTML = rootNodes.map((node) => {
return <TreeNode nodeClick={this.props.nodeClick} key={node.childId} node={node} level={0}/>
});
...
return (
<div className="treeContainer">
<div className="wrapContainer">
{rootNodesHTML}
</div>
</div>
);
This works great but only for the rootnodes, when I try to render the children (the childrenHTML variable is only populated after the parent is clicked on) I get the following error:TypeError: connectDragPreview is not a function
Leading me to believe that those react-dnd props that come from the "collect" function is not being passed to the rootnodes but not the children. It seems like it should to me because the same code should be executed for the parents as for the children as its the same class... really stuck here.
I am relatively new to react, and new to ideas like HOCs so all tips or suggestions are appreciated. Thank you!
I was able to get this working. Check out the example posted at the end of the thread in
https://github.com/react-dnd/react-dnd/issues/332.
Ultimately the solution was to wrap the TreeNode in a "DragContainer" with a very simple render method
render(){
const {...props} = this.props;
return <TreeNode {...props}/>
}
Then in the TreeNode render method, when rendering the child nodes render a DragContainer instead, passing in all the usual props.
childrenHTML = this.state.children.map((child) => {
return <DragNodeContainer modalFunctions = {this.props.modalFunctions} nodeClick ={this.props.nodeClick} parentNode={this} key={child.childId} node={child} level={this.state.level+1} />;
});
I am still unsure as to the technical reason for this, however, the fix seems to work for other people and it works for me!
I have the following ReactJS component:
class Menu1item extends React.Component{
render(){
return (
<div>
{this.props.glyph}{this.props.value}
</div>
)
}
}
The component is used like below:
<Menu1item glyph={menu.glyph1} value={menu.menu1}/>
And menu is like below:
menu={menu1: 'YOU', glyph1: '<span class="icon"></span>'}
The component is rendered like below:
I wonder how I can actually render the span element.
Applied the suggested solutions and now it works fine:
Try removing quotes around '<span class="icon"></span>'.
This should do it:
const menu = {
menu1: 'YOU',
glyph1: (<span class="icon"></span>)
};
Explanation:
You are passing a string literal to the glyph prop, so it is literally rendering the string '<span class="icon"></span>', as expected. If you pass a <span> instead, then it should render a <span> like you want it.
Remember, you are using JSX, so you can write HTML-style tags without quotes, and they will be compiled to React.createElement() calls.
EDIT:
Since class is a reserved word, React uses the className prop instead. So you should actually write
const menu = {
menu1: 'YOU',
glyph1: (<span className="icon"></span>)
};
Thanks to #novaline for catching this.
You need dangerouslySetInnerHTML:
render() {
return (
<div>
<span dangerouslySetInnerHTML={{__html: this.props.glyph}}></span>
{this.props.value}
</div>
)
}
In the following example this.refs.foo.clientWidth returns undefined and I can't figure out why. How can I get the reference to SomeComp in PageComp to use its width? (using React 15.2.1 or similar)
class PageComp extends React.Component {
componentDidMount() {
console.log(this.refs.foo.clientWidth);
}
render() {
return (
<div>
<p>{this.props.name}</p>
<SomeComp ref="foo" />
</div>
);
}
}
class SomeComp extends React.Component {
render() {
return (
<div>
<h1>I loaded</h1>
</div>
);
}
}
ReactDOM.render(
<PageComp name="Joe Schmoe"/>,
document.getElementById('react_example')
);
JSBIN
this.refs.foo returns React Element.
But if you want to work with DOM element - you need to find this Node
React 15.0.1 Requires this syntax: ReactDOM.findDOMNode(this.refs.foo)
JSBIN:
http://jsbin.com/xabidaquti/1/edit?html,js,console,output
Try like this ReactDOM.findDOMNode(this.refs["foo"].clientWidth)
For better clarity, this.refs.foo.clientWidth will work if the refs is set to html elements like div, input and so on. As refs by itself will return the DOM Node in case of such html elements.
If the refs is set to some React components, then we can access the DOM Node of the Components only using ReactDom.findDOMNode(this.refs.foo) and hence we need to get the clientWidth using ReactDom.findDOMNode(this.refs.foo).clientWidth.
Ref
I'm trying render an element which has an accent character using ReactJS and JSX, but it's not returning what I wanted.
My JSX:
var Orcamento = React.createClass({
render: function() {
return (
<div>
<h1>Orçamento</h1>
</div>
);
}
});
React.render(
<Orcamento/>,
document.getElementById("orcamento")
);
My rendered javascript:
var Orcamento = React.createClass({displayName: "Orcamento",
render: function() {
return (
React.createElement("div", null,
React.createElement("h1", null, "Orçamento")
)
);
}
});
React.render(
React.createElement(Orcamento, null),
document.getElementById("orcamento")
);
And my result in browser:
Orçamento
I've set <meta charset="UTF-8"> in my index file inside the head tag, accent characters works in page title and body if this word is typed direct in page content, but is not working when it's rendered by ReactJs
How can I fix this problem?
I resolved! the problem is because I'm compiling JSX using gulp, and file generated is not UTF-8, so I save as file in UTF-8 that is working!
What you see, Orçamento, it's a result of a UTF-8 byte array being rendered in ASCII, probably codepage ISO 8859-1.
ReactJS doesn't support non-ASCII characters within HTML.
Try this:
var Orcamento = React.createClass({
render: function() {
return (
<div>
<h1> { 'Orçamento' } </h1>
</div>;
);
}
});
Or simply replace orçamento by Orçamento.
This is well explained in the JSX gotchas.
Also using the charset utf-8, try using this library:
https://github.com/mathiasbynens/he
import { decode } from 'he';
class Post extends Component {
render() {
<h1>{ decode(this.props.post.title) }</h1>
}
}