What is Render in React?
React takes over the manipulation of DOM with the use of the React.createElement function so that we don’t have to do it manually. Instead, updates are done only when needed. We only describe how we want the DOM to look with JSX or pure createElement function, and React creates a virtual representation of DOM. Then, based on it, the real DOM will be updated whenever there are differences after the state changed. What’s more, if there are many DOM updates scheduled, React can batch them for efficiency. Nevertheless, this whole process consists of three stages: Render, Reconciliation, and Commit.
Render – React calls the render function to gather output from createElement functions
Reconciliation – New elements are compared against previously given elements and the virtual DOM is updated if there are differences
Commit – The real DOM is updated
Like I mentioned before, changing the state does not mean that the commit phase will be executed, as there will be no need for it if there were no changes in the virtual DOM. As you can see in the example below, no matter how many times we click the button, the name property is set to the same value, despite the fact that we call the setState method.
class App extends Components {
state = {
name: ‘Thomas’
}
onClickHandler = () => {
this.setState({name: ‘Thomas’})
}
render() {
<div>
<p>My name is {this.state.name}</p><br/>
<button onClick={this.onClickHandler}>Click me</button>
</div>
}
}
If you put a console log in the render function, you will see that it will be called. However, if you check the DOM in the inspector, you won’t see a flash that indicates a change in DOM. Now, let’s talk about how we can trigger a re-render.
Forcing Re-render of a Component in React
If you are using a React class component then it is as easy as using this.forceUpdate() function.
class App extends Components {
onClickHandler = () => {
this.forceUpdate()
}
render() {
<button onClick={this.onClickHandler}>Click me</button>
}
}
Just make sure that this context refers to the component instance. In the example below, this refers to the scope of the inner function and not of the React component instance, and because of that, it won’t work.
// This won’t work
class App extends Components {
onClickHandler = () => {
function innerFunction() {
this.forceUpdate()
}
innerFunction()
}
render() {
<button onClick={this.onClickHandler}>Click me</button>
}
}
Now you know how easy it is, but be aware that in 99.99% of cases you should not need it. If you do, then you might be doing something wrong, and probably there is a better solution to what you are trying to achieve. The benefit of the force update function over setState is the fact that it will update a component even if the shouldComponentUpdate lifecycle hook is implemented.
If you are updating state values, but they are not rendered correctly, then instead of providing a new value, you might be directly mutating the current state. There is also a possibility that you are passing the same reference. Remember that when updating the state, you should always provide a new value. For example, strings are immutable; however, objects and arrays are passed as a reference, so:
/ Equality check is done by checking if values are the same
const str1 = ‘hello’
const str2 = ‘hello’
str1 == str2 // true
// Equality check is performed by checking if values have the same reference
const obj1 = {str: ‘hello’}
const obj2 = {str: ‘hello’}
const obj3 = obj1
ob1 == obj2 // false
obj3 == obj1 // true
Forcing a Re-render in a Functional Component
In a function component, there is no forceUpdate method. However, we can mimic this functionality with the code below.
import React, {useState} from ‘react’
const App = props => {
const [count, setCount] = useState(0)
const onClickHandler = e = => {
setCount(prevCount => prevCount + 1)
}
return (
<button onClick={onClickHandler}>Click me</button>
)
}
As you can see, whenever we need the component to be re-rendered, we just increment the counter. To be honest, we can go even further than that and create a custom hook for it.
import React, {useState} from ‘react’
const useForceUpdate = () => {
const [count, setCount] = useState(0)
const increment = () => setCount(prevCount => prevCount + 1)
return [increment, count]
}
const App = props => {
const [forceUpdate] = useForceUpdate()
const onClickHandler = e => {
forceUpdate()
}
return (
<button onClick={onClickHandler}>Click me</button>
)
}
Now you have seen how to force re-render of a component. If for any reason you would like to re-render a child component from a parent, then you can do it by changing its prop as shown below.
const ChildComponent = props => {
return (
// child markup
)
}
const App = props => {
const [forceUpdate, forceUpdateValue] = useForceUpdate()
const onClickHandler = e => {
forceUpdate()
}
return (
<div>
<ChildComponent key={forceUpdateValue} />
<button onClick={onClickHandler}>Click me</button>
</div>
)
}
In this article, we covered what render is in React, what happens when state is updated, and how to force a re-render in class and functional components. For the final note, remember, if you ever think that you need to force a re-render, think again as there might be a better way.
Top comments (0)