리덕스의 동작이 어떻게 이루어지는 지 대충 훑어봤다. state를 단순히 등록하고 가져오는 것 뿐만 아니라 해당 state가 어떻게 변하게 할 것인지, state가 변했을 땐 해당 state를 사용하는 컴포넌트에 렌더링을 일으켜 주는 등 global state를 관리해준다는 느낌을 받았다.
그럼 이제 context가 뭔지 알아보자.
props drilling이 발생했을 때 props 내려주기를 극복하기 위해 등장한 개념.
import { PropsWithChildren, createContext, useContext } from "react";
const MyCotext = createContext<{ hello: string } | undefined>(undefined);
const ContextProvider = ({
children,
text,
}: PropsWithChildren<{ text: string }>) => {
return (
<MyCotext.Provider value={{ hello: text }}>{children}</MyCotext.Provider>
);
};
const useMyContext = () => {
const context = useContext(MyCotext);
if (context === undefined) {
throw new Error(
"useMyContext는 ContextProvider 내부에서만 사용할 수 있습니다"
);
}
return context;
};
const ChildComponent = () => {
const { hello } = useMyContext();
return <h3>{hello}</h3>;
};
export const ParentComponent = () => {
return (
<ContextProvider text="react">
<ChildComponent />
</ContextProvider>
);
};
useContext를 함수형 컴포넌트 내부에서 사용할 때는 항상 컴포넌트 재활용이 어려워진다는 점을 염두에 둬야 함.
useContext가 선언되어 있으면 Provider에 의존성을 가지고 있는 셈이 되므로 아무데서나 재활용하기에는 어려워질 수 있음.
책에서 발췌한 나를 관통하는 내용이 있어 옮겨적어보겠다.
일부 리액트 개발자들이 콘텍스트와 useContext를 상태 관리를 위한 리액트의 API로 오해하고 있다는 것이다. 엄밀히 따지면 콘텍스트는 상태를 주입해주는 API다. 상태 관리 라이브러리가 되기 위해서는 최소한 다음 두 가지 조건을 만족해야 한다.
1. 어떠한 상태를 기반으로 다른 상태를 만들어낼 수 있어야 한다.
2. 필요에 따라 이러한 상태 변화를 최적화 할 수 있어야 한다.
하지만 context는 둘 중 어느것도 하지 못한다. 단순히 props값을 하위로 전달해 줄 뿐, useContext를 사용한다고 해서 렌저링이 최적화되지도 않는다.
확실히 redux는 state를 등록, 관리해주는 느낌이었지만 context는 위에서 기술한것처럼 일단 반드시 state를 내보내지 않아도 될 뿐더러 단순히 어떤 값이 필요해서 꺼내쓰기만 하는 느낌이었다. 이를 global state로 응용하기 위해 useState, useReducer등을 함께 사용하는 것 뿐인 거 같다
📘 참고 : 모던 리액트 Deep dive - Chapter3