Context에 대해 새로 알게된 내용이 있어 정리해본다. 또 Context를 이용한 Custom Hook을 만들어보자!
count를 context에서 관리하는 예를 보자.
// src/contexts/count-context.js
import { createContext, useContext, useState } from 'react';
const CountContext = createContext();
export const CountProvider = ({ children }) => {
const [ count, setCount ] = useState(0);
const plusCount = () => setCount((prev) => prev + 1);
const minusCount = () => setCount((prev) => prev - 1);
return (
<CountContext.Provider value={{ count, plusCount, minusCount }}>
{children}
</CountContext.Provider>
);
};
export const useCount = () => useContext(CountContext);
컨텍스트에 있는 count는 Counter 컴포넌트에서 사용하고, plusCount는 Plus, minusCount는 Minus 컴포넌트에서 사용한다고 가정해보자. 그리고 이 세 컴포넌트는 Container 컴포넌트의 children이다.
🚀 여기서 중요한 것은 setState를 바로 공유하지 않고, 상태를 변경하는 함수를 전달한다는 것이다. 🚀
Consumer가 될 컴포넌트를 Provider로 감싸면 Provider로 감싸진 하위 컴포넌트들은 컨텍스트에 접근할 수 있게된다.
import { CountProvider } from '../contexts/counter-context';
...
<CountProvider>
<Counter />
<Plus />
<Minus />
<Other />
</CountProvider>
<Other />
...
context에서 관리되고 있는 count, plusCount, minusCount는 각각<Count, Plus, Minus 컴포넌트에서 쓰인다.
import { CountContext } from '../contexts/counter-context';
...
return (
<CountContext.Consumer>
{(ctx) => {
..ctx.count,
..ctx.plusCount,
..ctx.minusCount
}}
</CountContext.Consumer>
);
...
// src/components/Count.js
import { useCount } from '@contexts/counter-context';
const Count = () => {
const { count } = useCount();
return <div>Count: {count}</div>
};
export default Count;
// src/components/MinusCount.js
import { useCount } from '@contexts/counter-context';
const MinusCount = () => {
const { minusCount } = useCount();
return <button onClick={minusCount}>-1</button>
};
export default MinusCount;
// src/components/PlusCount.js
import { useCount } from '@contexts/counter-context';
const PlusCount = () => {
const { plusCount } =useCount();
return <button onClick={plusCount}>+1</button>
};
export default PlusCount;
count, minusCount, plusCount는 컨텍스트에서 관리하고 있으며 이렇게 Counter를 사용하는 useCount라는 커스텀 훅으로 간단히 사용할 수 있다.
기본적으로 컴포넌트가 리렌더링되는 조건 중 하나가 자신의 state가 변경되는 경우이고, 또 다른 하나가 부모 컴포넌트가 리렌더링 되는 경우인데(props가 변경되는 경우도 컴포넌트가 리렌더링 됨.) counter-context에서 count를 useState로 관리한다. 즉 count값이 변경되면 CountProvider 컴포넌트가 리렌더링 되고 따라서 그 자식 컴포넌트인(children) Count, MinusCount, PlusCount가 전부 리렌더링 된다.
🚀 Context.Provider는 컴포넌트가 아니다. 따라서 count state가 변경된다 하더라도 children에 속하는 모든 하위 컴포넌트가 전부 리렌더링 되는 것은 아니다. useCount 훅을 사용하여 context에 접근하는 컴포넌트만 리렌더링된다!! 🚀

useCount 훅을 사용하지 않는 Other 컴포넌트가 CountProvider 하위에 위치한 경우 화면상 깜박거리며 표시되긴 하지만 콘솔을 확인해보면 첫 마운트 시에만 출력이 되었고 count가 변경되었을 땐 출력되지 않는 것을 확인할 수 있다.
