kooskoos
kooskoos

Reputation: 4859

Manipulating DOM in react

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

Answers (2)

Danziger
Danziger

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

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.

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

Oluwajuwon
Oluwajuwon

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

Related Questions