Alex Sidorenko

A Visual Guide to React Rendering - Context

August 19, 2021

This article is a 5th chapter of A Visual Guide to React Rendering.

When a component consumes context, and the value of this context changes, this component re-renders. But why does Component A and Component B also re-render in this example:

The components structure is App (ContextProvider) > A > B > C

const App = () => {
  // ...
  return (
    <AppContext.Provider ...>
      <ComponentA />
    </AppContext.Provider>
  )
}

const ComponentA = () => <ComponentB />
const ComponentB = () => <ComponentC />

Context and React rendering

From the first chapter, we know the default behavior of React rendering. When a component renders, React will recursively re-render all its children regardless of props or context. Let’s remove the context from our example and see this behavior in action.

From the same chapter, we learned that to stop this recursive re-rendering, we can use memo. Let’s apply memo to the initial example.

Therefore 👇

Context and references

In real-life apps, we often need to pass more data to the context. Sometimes this data will rely only on certain specific state variables.

We pass a and b to the provider, but the consumer component re-renders even when count updates. How to prevent that?

Here is the hint - the text variable stores an object (non-primitive value). And… 👇

All consumers that are descendants of a Provider will re-render whenever the Provider’s value prop changes

React Docs - Context Provider

When we update the count value, the App component re-renders, leading to the redeclaration of the text variable. From the second chapter, we learned the difference between primitive and non-primitive values in javascript. We know that {a: "lorem", b: "ipsum"} !== {a: "lorem", b: "ipsum"} . It means that on every render of the App, the context value changes even if a and b don’t. And when the context value changes, the context consumer re-renders. To prevent that, we need to make sure that the text variable receives the same object reference. And from the third chapter, we know that we can do that with useMemo.

Now the text variable will only change when one of the values in useMemo dependency list changes. The count is not on the list. Therefore when the count changes, the text will get the previous reference, and the context consumer will not re-render.

Next chapter

A Visual Giude to React Rendering - DOM