useReducer와 useContext를 사용해서 전역 상태 관리를 해보자.
useReducer와 useContext를 같이 사용해보자.
왜 둘을 같이 사용해야할까?
전역 상태 값을 좀 더 세분화해서 다룰 수 있기 때문이다.
useReducer만으로도 충분한 경우가 있지만 애플리케이션이 커지다 보면 좀 더 세분화해서 다뤄야하는 경우가 이럴 때 useReducer와 useContext를 같이 사용하면 더 편하게 관리할 수 있다.
프로젝트 설정
root 디렉토리에 reducer 폴더를 만들어보자. 그리고 그 밑에 index.js 파일과 action.js 파일을 만들어보자.
// reducer/action.js
export const PLUS = "add";
export const MINUS = "minus";
// reducer/index.js
import { PLUS, MINUS } from "./action";
export const initialState = {
num: 0,
};
const reducer = (state, action) => {
switch (action.type) {
case PLUS:
return {
num: state.num + 1,
};
case MINUS:
return {
num: state.num - 1,
};
default:
return;
}
};
export default reducer;
action.js에서는 액션을 정의하고 index.js에서는 초기값과 리듀서를 정의했다.
만약 useReducer만을 사용하면 어떻게 될까?
import React, { useReducer } from "react;
import reducer, {initialState} from "./reducer;
const Counter = () => {
const [ state, dispatch ] = useReducer(reducer, initialState);
(...)
}
위와 같이 useReducer 훅을 이용해서 reducer와 initialState를 전달해서 state와 dispatch를 갖고 올 수 있다. 위와 같은 경우는 state에는 num이 있고, dispatch에는 두가지 타입(PLUS, MINUS)가 있다.
만약 여러 곳에서 사용한다면 계속 저렇게 불러와야할까?
단순히 num만 있는 것이 아니라 여러 객체가 있다면, 그 객체들을 계속 불러와야할까?
Context를 통해서 상황을 더 깔끔하게 분리할 수 있다.
context 추가하기
// context.js
import React, { createContext, useReducer, useContext } from "react";
import reducer, { initialState } from "./reducer";
const Context = createContext();
const ContextProvider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<Context.Provider value=>{children}</Context.Provider>
);
};
export const useDispatch = () => {
const { dispatch } = useContext(Context);
return dispatch;
};
export const useGlobalState = () => {
const { state } = useContext(Context);
return state;
};
export default ContextProvider;
컨텍스트를 만들어서 value에 state와 dispatch를 전달했다.
그리고 그 밑에 dispatch 부분과 state 부분을 나누었다.
만약 상황별로 state를 더 나누고 싶다면 useGlobalState 부분을 더 자세히 나눠서 사용하면 된다.
마지막으로 next app의 경우엔 _app.jsx에 컴포넌트를 감싸주면 된다.
// _app.jsx
function MyApp({ Component, pageProps }) {
return (
<ContextProvider>
<Component {...pageProps} />
</ContextProvider>
);
}
이제 간단히 사용할 수 있다.
const Test = () => {
const globalState = useGlobalState();
const dispatch = useDispatch();
(...)
}
위와 같이 state만 필요할 땐 state만 갖고오고, dispatch가 필요할 땐 dispatch만 들고오면 더 깔끔하게 사용할 수 있다.
Leave a comment