Speed up your react app by avoiding unnecessary re-renders

Published on Sun Jan 03 2021
Cover Image

The Problem

Let’s have a look at the problem. Here is a Product list, this list has another component called a product form, which opens up in a modal when you click the edit button. Now whether to hide or show the form is stored in a boolean in the list component’s state, but that is a problem! Why?!

Because when you click the edit button the state of the list changes to show the product form and that causes the whole list to re-render! doesn’t sound good does it. In a sufficiently complex app, this will cause a significant performance compromise.

If you open the console of the sandbox below, you can see the console.logs of the re-renders.

The unoptimised sandbox

The product data is from - fakestoreapi.com

How do you solve it?

Let’s see how we can solve this issue. A React component updates whenever its state or props change. Sometimes we may want to update some data in a component but not cause it to re-render, thats where we use the useRef Hook.

What is useRef?

Its a react hook that allows you to keep a reference throughout the lifecycle of a component, i.e. even if the component re-renders the value inside your useRef persists.

The value can be anything, even a DOM node. We use it to avoid re-renders, as updating the value stored in it won’t trigger a re-render like updating state does.

How does the edit work?

In the unoptimised version, when we have a list of cards and want to edit one of them, we give an edit button to each of the cards and pass a handler function to them to call on edit. When this button is clicked we pass the data of the clicked card to the form to make the edits.

In the new version we make use of the useImperativeHandle hook. We define 2 methods in the object we return from the hook.

open and setData

These methods can now be called from the parent component (i.e. the list component). So when edit is clicked, we call productForm.current.open() which will open the form, and productForm.current.setData(data) which will set the given data on the form.

The solution sandbox

Now if you have a look at the console of the solution sandbox, opening and closing the form doesn’t cause the whole list to re-render. Mission Accomplished!

Conclusion

You can use useRef and useImperativeHandle hooks to avoid unnecessary re-renders and potentially speed up your app. You can also use class based components as children and assign them a ref and call their methods without using useImperativeHandle, let’s cover that in another blog. Meanwhile you can check out some of the resources that helped me learn these hooks. Note*: React advises you refrain from using imperative code, i.e. calling a child component’s methods is considered bad practice, so use these hooks carefully.*

References

Call child method from parent React.js component - fabiofranchino.com

The Complete Guide to useRef() and Refs in React - dmitripavlutin.com