The biggest pitfall of React Context - unwanted re-render
Usually, in small apps, people create a global context to share state across the application.
In the following example,We have a global context:
1import { createContext, useContext, useState } from 'react';
2
3type ContextType = {
4 stateOne: string;
5 stateTwo: string;
6 setStateOne: React.Dispatch<React.SetStateAction<string>>;
7 setStateTwo: React.Dispatch<React.SetStateAction<string>>;
8}
9
10const GlobalContext = createContext<ContextType>({
11 stateOne: '',
12 stateTwo: '',
13 setStateOne: () => null,
14 setStateTwo: () => null,
15});
16
17export const GloBalProvider:React.FC<{children: React.ReactNode}> = ({ children }) => {
18 const [stateOne, setStateOne] = useState('111');
19 const [stateTwo, setStateTwo] = useState('222');
20
21 return (
22 <GlobalContext.Provider
23 value={{
24 stateOne,
25 setStateOne,
26 stateTwo,
27 setStateTwo
28 } }
29 >
30 {children}
31 </GlobalContext.Provider>
32 );
33};
34
35export const useGlobalContext = () => useContext(GlobalContext);Using that context:
1import { useEffect } from 'react';
2import { GloBalProvider, useGlobalContext } from './GlobalContext';
3
4const ChildOne = () => {
5 const { stateOne, setStateOne } = useGlobalContext();
6 useEffect(() => {
7 console.log('TestContext ChildOne rerender');
8 });
9
10 return (
11 <>
12 <div>child one: {stateOne}</div>
13 <button onClick={() => setStateOne('abc')}>change stateOne</button>
14 </>
15 );
16};
17
18const ChildTwo = () => {
19 useGlobalContext();
20
21 useEffect(() => {
22 console.log('TestContext ChildTwo rerender');
23 });
24
25 return <span>child two</span>;
26};
27
28const TestContext = () => {
29 return (
30 <>
31 <GloBalProvider>
32 <ChildOne />
33 <br />
34 <ChildTwo />
35
36 </GloBalProvider>
37 </>
38 );
39};let's run the code:

When we change stateOne, we can see that the ChildTwo component re-renders even though it doesn’t use stateOne at all.
Even with React.memo wrapping around ChildTwo, it still doesn’t work.
That’s the problem with Context — every time a state inside the context changes, it triggers a re-render of every component that consumes the context.
Moreover, putting everything inside a global context in a large application will create a mess that’s really hard to maintain.
Conclusion: in a large application with complex data and flows, we should use a state management tool like Redux instead