Optimise rendering of children tree subscribed to Context API
Tags: react, javascript
Published: 2020-09-14 11:26:43

---
title: Optimise rendering of children tree subscribed to Context API
published: true
description: A few months ago, I got to develop a web application that required optimal state management in the sense that each component in the application needs to re-render only when changes are made to state data bound to the component
tags: #ReactJS #JavaScript
cover_image: https://cdn.pixabay.com/photo/2016/08/17/16/04/egg-1600890_960_720.jpg---
 
A few months ago, I got to develop a web application that required optimal state management in the sense that each component in the application needs to re-render only when changes are made to state data bound to the component. Thinking of the perfect architecture that seemed to fit the project, I came up with an architectural pattern which followed the rule stating that the app should be contained in a global state manager ( that holds data that rarely *change* such as authentication data) and also each route should have its own state manager ( Context API), hence to prevent unnecessary re-render whenever there's a change in data other routes.

>This article assumes that you as a reader have some experience with state management using React. If you are new to React state management, I recommend that you check out this [article](https://kentcdodds.com/blog/application-state-management-with-react) by Kent Dodds before proceeding.
 
{% gist https://gist.github.com/calebdeji/190bc7f8c3aa95d7c945385c08ad7a71 %}

Notice how each route encompasses a state manager that contains the route component. Putting this kind of structure in place is particularly important for the sake of readability, scalability, and maintainability. It is easy to handle errors in each route’s state manager, and *separation of concern* actually makes development easy.


I completed the project and it seemed perfect but then I noticed that each component subscribed to each route state manager re-rendered whenever changes were made to data held by the manager. The following is an example of what I meant

{% gist https://gist.github.com/calebdeji/4a07ba546e9f7eecb785ea5f5a2b469d %}

###This is cool, so what is the problem?
 
It works pretty well. However, the issue is that for every update made in the context data, all components that subscribed to the context API re-renders. We really do not want each expensive component subscribed to a particular context manager to re-render every time we update the state even though the data attached to the component didn't change. What shall we do to prevent this?

###What's the solution to the problem then?

If we were using class-based components, we could easily prevent re-renders with the ***shouldComponentUpdate*** method or employ the use of pure React components that are made for issues like this but these are functional components. Don't be scared, we have a savior called `useMemo`. *`useMemo`??* Ah Yes.


> useMemo is a built-in React hook that returns a memoized value. It allows you recompute expensive functions only when one of the dependencies has changed

**Note the following:**

> useMemo will only recompute the memoized value when one of the dependencies has changed. This optimization helps to avoid expensive calculations on every render. Remember that the function passed to `useMemo` runs during rendering. Don’t do anything there that you wouldn’t normally do while rendering.  For example, side effects belong in the [`useEffect` hook](https://reactjs.org/docs/hooks-reference.html#useeffect), not `useMemo`. You can read more on `useMemo` [here]( https://reactjs.org/docs/hooks-reference.html#usememo).

How do we use `useMemo` in this kind of scenario? The answer to the “how” is shown in the code snippet below.
 
{% gist https://gist.github.com/calebdeji/8eec1fa1768ea7c8e2e346f92c3d2740 %}


> **Note**: Our components would still re-execute, but React wouldn't re-render the child tree if all useMemo inputs were the same.

This pattern helps us to solve the problem we have at hand - any child of each component that subscribed to a particular context API only re-renders when the necessary data attached to its `useMemo` changes.

Context API shouldn't be used as a global state manager that holds data that changes frequently for performance's sake, you can use Redux for that. Thanks for reading.

Feel free to drop suggestions and questions in the comments section below.