When using React components in combination with Context
, you can optimize rendering by wrapping your React component with React.memo right after your context provider. This will prevent unnecessary re-renders.
Here are some examples of how re-rendering works with Context
:
Example 1:
// App (ContextProvider) > A > B > C
const App = () => {
return (
<AppContext.Provider>
<ComponentA />
</AppContext.Provider>
);
};
const ComponentA = () => <ComponentB />;
const ComponentB = () => <ComponentC />;
const ComponentC = () => null;
In this example, if the App
component re-renders, all components within it will also re-render, regardless of whether or not their props
have changed.
Example 2:
To prevent the re-rendering of all ComponentA
, ComponentB
, and ComponentC
if the App component re-renders, you can use React.memo
as follows:
// App (ContextProvider)
const App = () => {
return (
<AppContext.Provider>
<ComponentA />
</AppContext.Provider>
);
};
const ComponentA = React.memo(() => <ComponentB />);
const ComponentB = () => <ComponentC />;
const ComponentC = () => null;
Example 3:
// App (ContextProvider) -> C
const App = () => {
const value = {a: 'hi', b: 'bye'};
return (
<AppContext.Provider value={value}>
<ComponentA />
</AppContext.Provider>
);
};
const ComponentA = React.memo(() => <ComponentB />);
const ComponentB = () => <ComponentC />;
const ComponentC = () => {
const contextValue = useContext(AppContext);
return null;
};
In this example, even though the provider value doesn't seem to change, ComponentC
gets re-rendered. This is because, in JavaScript, the below assertion is true
:
{a: 'hi', b: 'bye'} !== {a: 'hi', b: 'bye'}
Example 4:
The problem in Example 3 can be resolved by using the useMemo hook from React as follows.
// App (ContextProvider)
const App = () => {
const a = 'hi';
const b = 'bye';
const value = useMemo(() => ({a, b}), [a, b]);
return (
<AppContext.Provider value={value}>
<ComponentA />
</AppContext.Provider>
);
};
const ComponentA = React.memo(() => <ComponentB />);
const ComponentB = () => <ComponentC />;
const ComponentC = () => {
const contextValue = useContext(AppContext);
return null;
};
With this implementation, if the App re-renders for any other reason that does not change any of the 'a' or 'b' values, the sequence of re-renders will be as follows:
App (ContextProvider)
This results in the desired outcome of avoiding an unnecessary re-render of ComponentC
. By using useMemo
, the same object reference for the value
variable is guaranteed. Since this variable is assigned to the provider's value
, the context is determined to be unchanged, and no consumers are notified.
Summary:
This blog post provides information on optimizing rendering when using React components with Context by using React.memo. It includes examples of how re-rendering works with Context and how to prevent unnecessary re-renders using React.memo.
Top comments (0)