DEV Community

Husnain Mustafa
Husnain Mustafa

Posted on • Edited on

Improve performance of React Application

Performance is the major issue when we develop a medium to large scale projects. React provide us various ways through which we can improve the performance of our react app. Most of it are the hooks that are provided by react, but performance issue is not limited to that. Most of the performance issues in React is because of the re-rendering of the components. So let's discuss about it.

Re-rendering in React:

If you know react, you would know that whenever the props or states gets changed, component re-renders. And not only re-renders it self but all the children also gets re-rendered all the way to the leaf node, i.e last child in the DOM tree, when the parent gets re-rendered.
Furthermore, when component re-renders, it not only affects the DOM, but also re-declare/re-define every variable and function which is the part of the component. This further effects the performance.

Minimizing the re-rendering ripple effect:

Preventing child component to re-render whenever parent re-render:

We can prevent the child component re-rendering on parent re-rendering by use React.memo. By using React.memo, our child component only gets re-rendered only if its props gets changed. So even if our parent is getting re-render, regardless what the reason is, if the props passed to children are not changed, then child component will not re-render.
Here is the example:

...
...
const ChildComponent = ({arg1, arg2}) => {
...
...
}

export default React.memo(ChildComponent)
Enter fullscreen mode Exit fullscreen mode

Preventing the re-defining of the functions on re-render:

Almost all of our functions in the component does not need to be re-defined on the re-render, or we only need to redefine those only if some specific states gets changed. So we can prevent functions to be re-defined on every re-render by using useCallback hook. This hook stores the function and only re-define it if any variable provided in the dependency array gets changed. So we need to provide every variable in the dependency array that is not a part of function but used in function, like:

...
...

const Component = ({arg1, arg2}) => {

     const [myState, setMyState] = useState(0)
     const doSomething = useCallback(()=>{
          <do something with myState>
     }, [myState])
}
Enter fullscreen mode Exit fullscreen mode

In the above example, notice I have added myState in the dependency array. This is because, if I do not add myState in dependency array, doSomething will store the value of myState and always use that value. So even of myState value update to 3, doSomethinig will still be using 0 as myState. So to update our function with new value of myState, we need to add myState in dependency array.

Preventing the re-defining of the variable on re-render:

Some of the variables in the component needs to a very complex function, and then store the value returned by that function. So if we do not prevent this calling of a complex function, we can lose performance. To prevent this, we can use useMemo hook to store the value and provide those variables in the dependency array over which, when any of those variable gets updated, this complex function calculates and return the value again.

...
...

const Component = ({arg1, arg2}) => {

     const [myState, setMyState] = useState(0)
     const someValue = useMemo(() => complexFunction(myState), [myState])
}
Enter fullscreen mode Exit fullscreen mode

Preventing re-rendering when map function is used:

Have you noticed that whenever you use map, without use the prop 'key', it gives you warning. Key prop is useful for performance because React identifies and keep track of the components in the virtual DOM through the key prop. But when using map function, react does not automatically assign key to the components' array that is returned by map function. So if any only one component inside the map function changes, its will re-render all the components that are provided by the map function. So to avoid this re-rendering and restricting it to only re-render the component which got changed, we need to assign the key.

...
...
todoArr.map((el)=>{
     return(
          <TodoComponent key = {el.id} title = {el.title}/>
     )
})
...
...
Enter fullscreen mode Exit fullscreen mode

Preventing re-rendering of input:

Most of the beginners in React, including myself when I started learning React, use controlled inputs through state. Something like:

...
const [myInput, setMyInput] = useState(0)
...
...
<input value = {myInput} onChange = {(event)=>{setMyInput(event.target.value)}}
...
Enter fullscreen mode Exit fullscreen mode

This causes re-rendering of input whenever we type a single character.
So unless you need to make your input controlled, for any reason like validation of input, you should use uncontrolled input. Which you can do using useRef hook as shown below:

...
const myInputRef = useRef()
...
...
<input ref = {myInputRef}/>
Enter fullscreen mode Exit fullscreen mode

and get the value of input by:
myInputRef.current.value


These are some of the ways you can improve performance of your react application. There are many other factors which affect the performance which I might have skipped.

Hope this article helped you.

Top comments (0)