In order for React to be as fast as it is, it only needs to update the parts of the DOM that need it. You really don’t need to worry about doing this yourself, but understanding how setState()
in React works could be beneficial.
render()
FunctionThe render()
function in React creates a tree of React elements. When you pass props down and those props update, the render()
function returns a different tree of elements. React would need to figure out how to accomplish this, and, while doing so, make it efficient and fast.
This tree of elements is called the virtual DOM and when a component’s state changes, React uses a diffing algorithm to compare both the DOM and virtual DOM. The virtual DOM will contain the new state of a component.
Take this code from CSS-Tricks:
class App extends React.Component { state = { result: '', entry1: '', entry2: '' } handleEntry1 = (event) => { this.setState({entry1: event.target.value}) } handleEntry2 = (event) => { this.setState({entry2: event.target.value}) } handleAddition = (event) => { const firstInt = parseInt(this.state.entry1) const secondInt = parseInt(this.state.entry2) this.setState({result: firstInt + secondInt }) } render() { const { entry1, entry2, result } = this.state return( <div> <div> <p>Entry 1: { entry1 }</p> <p>Entry 2: { entry2 }</p> <p>Result: { result }</p> </div> <br /> <div> Entry 1: <input type='text' onChange={this.handleEntry1} /> </div> <br /> <div> Entry 2: <input type='text' onChange={this.handleEntry2} /> </div> <div> <button onClick={this.handleAddition} type='submit'>Add</button> </div> </div> ) } }
We set up the initial state to an object which will expect some input. This is the App
component. When an input is captured in the entry field, React will create a new tree to which the virtual DOM and will contain the new state for entry1
. React will look at both the virtual DOM and the browser DOM and with comparison determine what the differences are and update only the different element in the tree.
A new tree/virtual DOM is created each time state changes in the App
component.
When state in a component changes, React will unmount the component and tear the whole tree down and then builds a new one from scratch. Every node in this tree will be destroyed.
To get a sense of this, check out the code below:
const Link = () => ( <div>This is a link component</div> ) class App extends React.Component { state = { change: true } handleChange = (event) => { this.setState({change: !this.state.change}) } render() { const { change } = this.state return( <div> <div> <button onClick={this.handleChange}>Change</button> </div> { change ? <div> This is div cause it's true <h2>This is a h2 element in the div</h2> <Link /> </div> : <p> This is a p element cause it's false <br /> <span>This is another paragraph in the false paragraph</span> <Link /> </p> } </div> ) } } ReactDOM.render(<App />, document.getElementById("root"));
The way React handles state and state changes makes it really fast. You’ll need to be careful to adhere to its heuristics and conventions or else performance will degrade. With that said, it is pretty easy to build a performant app in React.
There are a few things I didn’t go over in this article but I suggest you read the React docs on reconciliation.
This post first appeared on my blog.
P.S. If you like what I am doing here, be sure to subscribe, follow me on Twitter, buy me a coffee, a book, or support me on Buy Me a Coffee and share the love. You can also subscribe to this newsletter’s rss feed or you can ask me anything.
👋🏾 Hi. I’m Tiffany White. I am a front-end engineer and egghead.io instructor. I sometimes contribute to open source, and blog about web development at Tiffany R. White Blog. I love JavaScript, React ⚛️, and herding cats 🐾 🐈