useReducer, useContext - 리덕스를 대체할 수 있는 react hooks

GY·2021년 11월 28일
0

리액트

목록 보기
22/54
post-thumbnail

redux를 공부하면서 작성한 지난 포스팅에서 redux를 사용하는 이유와 더는 필수가 아니게 된 이유에 대해 공부했다. 리액트 훅으로 리덕스를 대체할 수 있는 방법에 대해 공부할 차례다!

🖲 왜 필요할까?

prop drilling

리액트는 데이터를 전달하기 위해 상위 컴포넌트에서 각각의 하위 컴포넌트를 모두 거쳐야 했다.
이것을 prop drilling이라고 한다.
이것을 해결하기 위해 리액트 컴포넌트와 독립적으로 움직이는 리덕스 스토어를 이용했지만 리덕스는 굉장히 번거로운 점이 많고 세팅에도 필요한 과정이 많았다. 더군다나 이제는 리액트 훅 중 useReducer, useContext를 사용할 수 있게 되어 redux가 필수적으로 필요하지 않게 되었다.

복잡한 state update

useState를 사용하면 일일히 많은 상태를 업데이트하기 위한 코드를 작성해 가독성이 급격하게 떨어지게 된다.



🖲 독립적인 상태관리를 위한 react hooks

🕹 useReducer

const [state, dispatch] = useReducer(reducer, initialArg, init);

useState의 대체 함수이다.

reducer

(state, action) => newState의 형태로 reducer를 받는다.
즉, reducer, action을 인자로 받는다.
1. action객체가 dispatch되면
2. reducer 함수에 state와 action객체를 매개변수로 실행한다.
3. 현재 state를 action type을 기준으로 업데이트한 뒤 반환한다.


🕹 useContext

useContext는 React.createContext가 반환한 context 객체를 인자로 받는다.
그 후 useContext가 호출된 컴포넌트로부터 가장 가까이 있는 해당 context의 Provider를 찾아서 그 Provider의 value를 반환한다.

즉, 최상위 컴포넌트를 context.Provider로 감싸준다면 코드 전역에서 해당 context를 참조할 수 있다.

또한 useContex를 호출한 컴포넌트는 해당 context의 값이 변경되면 항상 리렌더링 된다.
다만, context에 담긴 값을 하위 컴포넌트에서 수정할 수는 없다.


🕹 useReducer + useContext

useReducer와 useContext를 조합하면 redux처럼 사용할 수 있다.
useReducer로 state와 dispatch를 생성한 다음,
useContext를 이용해 하위 컴포넌트가 이 값에 접근하고 수정할 수 있도록 만들어준다.

1. createContext로 context 생성하기

export const countStateContext = createContext(0); // 3
export const countDispatchContext = createContext<Dispatch<CountActionT> | null>(null); // 3

2. context.Provider로 컴포넌트에 state와 dispatch전달하기


const App = () => {
  const [state, dispatch] = useReducer(countReducer, initialState); // 2

  return (
    <countDispatchContext.Provider value={dispatch}> // 4
      <countStateContext.Provider value={state.count}>
        <Count />
      </countStateContext.Provider>
    </countDispatchContext.Provider>
  );
};

App의 모든 하위컴포넌트에서 countState와 countDispatch를 사용할 수 있다.

3. 전달한 count 컴포넌트에서 useContext사용하기

import React, { useContext } from 'react'
import { countDispatchContext, countStateContext } from '../App'

const Count = () => {
  const count = useContext(countStateContext); // 5
  const dispatch = useContext(countDispatchContext);

만든 context를 임포트해와 useContext에 인자로 전달해준다.

4. state 변경

  return (
    <div>
      <p>Test count: {count}</p>
      <button onClick={() => {dispatch({type: 'INCREASE'})}}>+</button>
    </div>
  )
}



Reference

profile
Why?에서 시작해 How를 찾는 과정을 좋아합니다. 그 고민과 성장의 과정을 꾸준히 기록하고자 합니다.

0개의 댓글