Context를 사용하기 위해 뒤적뒤적 검색을 하면서 이해를 하는 데에 애를 먹었다.
이해를 한 후에 나 같은 주니어 개발자가 조금 더 쉽게 이해할 수 있도록 이 글을 최대한 쉽게 풀어 설명해본다.
쉽게 설명한다고 설명했는데 어려운 부분이 있으면 댓글주세요~
아마 천천히 읽어본다면 이해할 수 있을 거라고 생각한다.
React에서 데이터는 부모 컴포넌트에서 자식 컴포넌트에게 단방향으로 props를 통해 전달된다. 컴포넌트가 늘어날수록 props를 통해 전해주는 과정은 번거로워진다.
Context는 트리 단계마다 명시적으로 props를 넘겨주지 않아도 많은 컴포넌트에서 값을 공유할 수 있도록 해준다.
React 컴포넌트 트리 안에서 전역적(Global)으로 데이터를 공유할 때 사용하면 좋다.
- Context 생성 -
createContext()
- Context 제공 -
<Context.Provider value={{ ... }}>
- Context 사용 -
<Context.Consumer>, useContext()
Context를 사용하기 위해서는 아래처럼 일단 createContext로 Context를 만들어준다.
const NewContext = createContext(/* defaultValue */);
Context를 만들면 Context 안에 Provider를 통해서 value를 지정해줘야 한다.
쉽게 설명하면 value에 전역적으로 사용할 값들을 넣어주면 된다.
이렇게 value를 설정하였다면 이제 Global로 사용할 컴포넌트를 감싸주면 된다.
<NewContext.Provider
value={{
변수,
함수,
상태,
...
}}
>
<App />
</NewContext.Provider>
직접적으로 useState로 상태를 Global로 사용할 수도 있고, 또 useReducer란 Hook을 사용하여 상태를 관리할 수도 있다.
useReducer는 쉽게 설명하면 state의 관리를 좀 더 디테일하게 관리할 수 있는 useState의 대체 함수라고 생각하면 된다.
다수의 하윗값을 포함하는 복잡한 정적 로직을 만드는 경우나 이전 상태에 의존적인 경우에 useState보다 useReducer를 사용하는 게 좋다.
간단한 앱이나 복잡하지 않은 상태를 관리할 때는 useReducer보다 useState를 사용하는 것이 더 효과적일 수 있다.
useReducer는 다음과 같이 사용한다.
const [ state, dispatch ] = useReducer(reducer, initialState);
newState의 형태로 reducer를 받고 dispatch 함수와 짝의 형태로 현재 state를 반환한다.
const initialState = {count: 0};
function reducer(state, action) {
switch (action.type) {
case 'increment':
return {count: state.count + 1};
case 'decrement':
return {count: state.count - 1};
default:
throw new Error();
}
}
function Counter() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<>
Count: {state.count}
<button onClick={() => dispatch({type: 'decrement'})}>-</button>
<button onClick={() => dispatch({type: 'increment'})}>+</button>
</>
);
}
위의 코드는 React 공식 문서의 코드이다.
어떤 식으로 사용하는지 코드를 보고 감을 잡으면 좋을 것 같아 참조한다.
dispatch 함수를 통해 action을 보낸다. 그럼 reducer 함수에 따라 상태를 변환한다.
위의 코드를 useReducer가 아닌 useState를 사용하면 아래와 같다.
function Counter({initialCount}) {
const [count, setCount] = useState(initialCount);
return (
<>
Count: {count}
<button onClick={() => setCount(initialCount)}>Reset</button>
<button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
<button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
</>
);
}
위의 과정들을 거쳐서 Provider를 통해 value를 제공했으면 이제 받아서 사용하기만 하면 된다.
사용하기 위해서는 Consumer를 사용할 수 있다.
<NewContext.Consumer>
{value => /* context 값을 이용한 렌더링 */}
</NewContext.Provider>
Context.Consumer의 자식은 반드시 함수여야 한다.
Provider의 value props가 없으면 createContext()에 사용한 defaultValue의 값이 할당된다.
또 다른 방법으로는 useContext()를 사용하는 것이다.
const value = useContext(NewContext);
/* or */
const { 변수, 함수, 상태, ... (직접적으로 선언) } = useContext(NewContext);
Global로 사용할 값들을 useContext를 통해 선언하여 사용하면 된다.
물론 사용할 컴포넌트에서 선언해줘야한다.
React 공식 문서