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 👇
That React Component Right Under Your Context Provider Should Probably Use `React.memo`
— Sophie Alpert (@sophiebits) February 16, 2020
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
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.