티스토리 뷰
[React] useRedcuer & useContext 같이 사용 - state, 분리한 state 업데이트 로직을 전역에서 사용해보자
doeunnkimm 2023. 2. 26. 13:27
🚀 useReducer와 useContext 복습
useReducer는 state를 업데이트 하는 로직을 분리해서 dispatch를 통해서만 state를 업데이트했었습니다.
이때 dispatch에는 action 객체를 보내게 되는데요. 이 객체에는 원하는 로직과 필요한 데이터를 담아서 보냈었습니다.
useContext는 전역 상태 관리를 할 수 있는 hook 함수였습니다.
빈 저장소를 만들고 이 저장소를 useContext에 넘겨주게 됩니다.
최상위 컴포넌트로 방금 만든 저장소.Provider 하고 value로 전역에서 사용하고 싶은 데이터를 넘겨주면
props로 데이터를 넘겨주지 않아도 어떤 자식 컴포넌트에서 전역으로 관리되고 있는 데이터를 사용할 수 있었습니다.
→ 이 두 hook 함수를 함께 사용한다면 state를 전역에서 관리하는 동시에 분리한 state를 업데이트하는 로직도 전역에서 사용할 수 있을 것입니다.
🚀 우선 state를 담을 저장소, state업데이트 로직을 담을 저장소를 만들자
우선 src 폴더 안에 contexts라는 폴더에서 코드를 작성했습니다.
빈 저장소를 만들기 위해서는 createContext를 이용해야 했습니다.
const TodoListContext = createContext();
const TodoDispatchContext = createContext();
이제 전역에서 사용할 저장소를 useContext를 통해 전역에서 사용하는 것이었는데요.
저는 아예 useContext를 여기서 사용해서 변수 하나로 바로 스토어를 사용하도록 export하려고 합니다.
위 방법이 아니라면 매번 useContext(저장소이름) 이런식으로 useContext를 import해야 할 것입니다.
export const useTodoListState = () => useContext(TodoListContext);
export const useTodoDispatch = () => useContext(TodoDispatchContext);
위 코드에서 TodoListContext는 state 자체를 담을 저장소이고, TodoDispatchContext는 state를 업데이트하는 로직(=reducer)를 담을 저장소입니다.
🚀 저장소에 담을 state 업데이트 로직 = reducer를 만들어보자
두 번째 저장소에 담을 state 업데이트 로직 즉, reducer를 만들어 봅시다.
➕ createAction
우리는 switch 문을 통해 들어오는 action.type에 따라 다른 로직을 실행하도록 코드를 작성했었습니다.
그런데 switch문의 case에 들어가는 것은 문자열이라 하나라도 오타가 날 경우 전혀 실행이 안 될 것입니다.
따라서 createAction이라는 함수를 선언해서 사용하려고 합니다.
이 함수는 action.type에 들어갈 문자열을 인자로 받으면
payload만을 받을 수 있는 함수를 리턴하게 됩니다.
즉, 처음에 action.type을 넘겨주면 무조건 받은 그 type을 가지고 있는 함수를 리턴합니다.
그러면 이제 그 변수 안에 payload를 넘겨주면 알아서 (처음에 받은 타입, 사용할 때 받은 payload)로 사용할 수 있게 되는 것입니다.
export function createAction(type) {
return function (payload) {
return {type, payload};
};
}
export const ADD_TODO = createAction('ADD_TODO');
export const DELETE_TODO = createAction('DELETE_TODO');
export const UPDATE_TODO = createAction('UPDATE_TODO');
const todoReducer = (state, action) => {
switch (action.type) {
case 'ADD_TODO':
return [action.payload, ...state];
case 'DELETE_TODO':
return state.filter((todo) => todo.id !== action.payload.id);
case 'UPDATE_TODO':
const newTodo = [...state];
const todoIndex = newTodo.findIndex((todo) => todo.id === action.payload.id);
newTodo[todoIndex].content = action.payload.content;
newTodo[todoIndex].state = action.payload.state;
return newTodo;
default:
return state;
}
};
🚀 전역에서 관리할 value를 담고 있는 Provider 자체를 만들어서 export 하자
우리가 위에서 빈 저장소를 만들었고, 빈 저장소에 담을 데이터도 만들어 놓았으니 이제 담아서 최상단에서 사용해주기만 하면 됩니다.
우리가 useContext를 사용할 때 최상위 컴포넌트에서 저장소를 불러와서 useContext를 사용해서 전역에서 사용할 수 있도록 하여 저장소.Provider하고 value라는 인자에 그 저장소에 담을 데이터를 넣어서 전역에서 사용했었습니다.
그런데 이번에는 지금 저장소가 2개이기도 하고 바로 export로 사용할 수 있도록 미리 다 만들어 놓으려고 합니다.
const TodoProvider = ({ children }) => {
const [todoList, dispatch] = useReducer(todoReducer, initialState);
return (
<TodoListContext.Provider value={todoList}>
<TodoDispatchContext.Provider value={dispatch}>
{children}
</TodoDispatchContext.Provider value={dispatch}>
</TodoListContext.Provider value={todoList}>
)
}
export default TodoProvider;
위 코드에서 children은 해당 TodoProvider 컴포넌트 안에 들어오는 모든 자식 컴포넌트들을 의미합니다.
즉, 안에 들어오는 모든 자식 컴포넌트들이 value를 사용할 수 있다는 말과 같습니다.
🚀 마지막으로 최상위에서 Provider를 사용해주자
📄 App.js 파일
function App() {
return(
<TodoProvider>
//...
</TodoProvider>
)
}
export default App;
🚀 한번 사용해보자
우리가 애초에 빈 저장소를 만들 때 매번 useContext를 import해서 사용하는 게 아니라 바로 변수 하나로 사용할 수 있도록 코드를 작성했고 export도 시켜놨었습니다.
따라서 해당 변수를 import 해와서 바로 사용하면 되는데요.
const dispatch = useTodoDispatch();
return(
//...
dispatch(ADD_TODO(newTodo));
)
위와 같이 불러와서 dispatch안에 데이터를 담아서 전달해주면 됩니다.
그리고 dispatch에는 우리가 위에서 createAction을 통해 만들어 놓았던 함수를 통해 값을 넘겨줍니다.
'프론트엔드 > React' 카테고리의 다른 글
[React] 리덕스(Redux) - 상태 관리 라이브러리 (0) | 2023.02.26 |
---|---|
[React] Flux 패턴이란? (0) | 2023.02.26 |
[React] useContext로 전역 상태 관리를 하자 (0) | 2023.02.20 |
[React] useReducer로 상태 업데이트 로직을 분리하자 (0) | 2023.02.20 |
[React] 리액트 불변성? 불변성을 지켜야 하는 이유 (0) | 2023.02.18 |
- Total
- Today
- Yesterday
- JSP
- 리액트
- TypeScript
- 파이썬
- testing
- next.js
- 데이터분석
- 인프런
- styled-components
- react-query
- 스타일 컴포넌트 styled-components
- 자바
- jest
- frontend
- 자바스크립트 기초
- CSS
- 딥러닝
- rtl
- HTML
- 프론트엔드 공부
- Python
- 프론트엔드
- 자바스크립트
- react
- 프로젝트 회고
- 프론트엔드 기초
- 머신러닝
- 디프만
- 타입스크립트
- 리액트 훅
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |