Reputation: 4859
I am aware that manipulating DOM directly in react is not a considered a good practice. As react reconciliation engine will hit performance when comparing virtual DOM and real DOM
But what if I do something like this?
Scenario shown only to explain question. No answer is needed for this specific scenario but to this practice as general with the downsides
Scenario: 1
state = {
innerHTML : ""
}
document.getElementById("test").innerHTML = this.state.innerHTML
handleChange(){
//...handles change in state
}
Scenario: 2
state = {
color:"red"
}
document.getElementById("test").style.color = this.state.color
handleChange(color){
this.setState({color})
}
In such as scenario react is aware that it needs to re-render as I am changing the state there-by maintaining the consistency of both Virtual and Real DOM.
So in all such situations where I can use state to maintain consistency and make changes to real DOM is it still a bad idea to make changes to real DOM in this way?
Upvotes: 2
Views: 1697
Reputation: 21161
In that case, rather than setting innerHTML
directly, you should be using dangerouslySetInnerHTML
:
class Component extends React.Component {
state = {
innerHTML: '',
}
handleChange() {
this.setState({ innerHTML: '...' });
}
render() {
return <div dangerouslySetInnerHTML={ { __html: this.state.innerHTML } }></div>;
}
}
As stated in the docs:
dangerouslySetInnerHTML
is React’s replacement for usinginnerHTML
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 outdangerouslySetInnerHTML
and pass an object with a__html
key, to remind yourself that it’s dangerous.
Also, when using dangerouslySetInnerHTML
, React will ignore that part of the DOM when diffing the virtual DOM and the real DOM (reconciliation), so it will be more performant as it has less work to do.
And in any case, if you do:
document.getElementById('test').innerHTML = this.state.innerHTML;
At some point in your code, maybe in componentDidUpdate()
, and then render()
is called again (when you update the state or a parent component re-renders), your changes will be overwritten, so you would need to be constantly updating it, which might produce a small but noticeable flash and reduce performance, as each render will have to update the DOM 2 times (one from React and the other one from innerHTML
).
Upvotes: 2
Reputation: 81
you can look into using ReactRef instead of having to manipulate the DOM directly, it's easier, safer and more best practice.
check here
Upvotes: 2