React: using React component inside of dangerouslySetInnerHTML
dangerouslySetInnerHTML
expects a JS object with __html
property which should be valid HTML markup. Instead you are providing <MySubComponent />
there and expecting it to render that component's html. React won't process <MySubComponent />
there. dangerouslySetInnerHTML
as name suggests should be avoided. Moreover what you are trying to accomplish here can easily be done through React only.
const MySubComponent = React.createClass({
render() {
return (<li><p>MySubComponent {this.props.index}</p></li>);
}
});
const MyComponent = React.createClass({
render() {
let subComponentList = [];
[1,2,3,4,5].forEach(function(i){
subComponentList.push(<MySubComponent key={i} index={i} />);
});
return (
<ul>{subComponentList}</ul>
);
}
});
ReactDOM.render(<MyComponent />, mountNode);
Old question but for future wonderers I think I might have a solution to this but do note that this will definitely break your redux
flow if you're using it in your project.
Basically, you should have some id
in your dangerousSetInnerHTML
text.
The idea is to mount to that id
in the componentDidMount
lifecycle hook after your "dangerous HTML" has been mounted to DOM.
e.g.
const myStringHTML = `
<div id="someid">
some text in my dangerous html
</div>
`;
const MySubComponent = React.createClass({
render() {
return (<p>MySubComponent</p>);
}
});
...
let myStringHTML;
myStringHTML += "<ul>";
myStringHTML += " <li>";
myStringHTML += " <MySubComponent />";
myStringHTML += " </li>";
myStringHTML += "</ul>";
const MyComponent = React.createClass({
componentDidMount() {
ReactDOM.render(<MyComponent />, document.querySelector('#someid'));
}
render() {
return (
<div dangerouslySetInnerHTML={{__html: myStringHTML}}></div>
);
}
});
Do note that componentDidMount
will however not be called on component updates. For more info on this refer to the lifecycle hook of react.
Fair warning though that this does feel hacky and it is. This also has its limitations as I mentioned some above but there can be time where you have no other option but to use dangerousSetInnerHTML
and at times like this, this is an option. At other times do what @Rohit Singh Sengar suggested and try to do it in react
.
Another approach would be to open a react portal. Ensure that the element has rendered and then simply
ReactDOM.createPortal(<YourComponent>,document.querySelector('selector'));
This is the cleanest way so far i have found to achieve this.