React Context API, useReducer로 전역 상태 관리 만들기
2023/03/13
4 min read
DEVELOPMENT
Context API
- Context는 props드릴링을 줄이기 위해 사용합니다
- Context를 사용하면 props로 넘겨주지 않아도 하위 트리의 모든 구성 요소에서 해당 값을 사용할 수 있어요
useReducer
- useState와 비슷합니다 상태관리를 할 수 있어요
- useState가 더 적은 코드를 작성하지만 많은 이벤트 핸들러를 통해 값을 수정하는 경우 코드를 줄이는데 useReducer가 적합할 수 있어요
- useState는 상태 업데이트가 단순할 때 가독성이 좋지만 복잡해지면 어려울 수도 있어요 useReducer는 발생한 이벤트와 해당하는 로직을 명확하게 구분이 가능해요
Context 생성
우선 Context를 만들기 위해 CreateContext를 이용하여 만들어 줍니다
1
const TodoStateContext = createContext(null);2
const TodoDispatchContext = createContext(null);
State값을 관리할 Context와 dispatch함수를 관리할 Context 해서 두개의 ConText를 생성해줍니다
reducer 정의
useReducer에서 사용할 reducer를 만들어주겠습니다
1
todo = {2
id: number,3
content: string,4
isComplete: boolean,5
};
1
function reducer((state,action)){2
switch(action.type){3
case 'ADD_TODO':4
state.push(action.todo);5
break;6
case 'DELETE_TODO':7
return state.filter(prev => prev.id !== action.todo.id)8
default:9
throw new Error('Unhandle Action')10
}11
}
간단하게 todo추가와 삭제만 설정해두었습니다
Context.Provider
이제 Context.Provider로 감싼 컴포넌트를 만들어볼께요
1
function TodoProdiver({ children }) {2
const [state, dispatch] = useReducer(reducer, []);3
4
return (5
<TodoStateContext.Provider value={state}>6
{' '}7
//value: 공유할 값을 넣어준다8
<TodoDispatchContext.Provider value={dispatch}>{children}</TodoDispatchContext.Provider>9
</TodoStateContext.Provider>10
);11
}12
13
export default TodoProvider;14
15
export function useTodoState() {16
const state = useContext(TodoStateContext);17
if (!state) throw new Error('cannot find Provider');18
return state;19
}20
21
export function useTodoDispatch() {22
const dispatch = useContext(TodoDispatchContext);23
if (!dispatch) throw new Error('cannot find Provider');24
return dispatch;25
}
먼저 TodoProvider를 보시면 useReducer를 사용하여 아까 만들어 두었던 reducer를 추가해주고,초기값은 []로 설정해주었습니다 return에는 만들어 두었던 Context.Provider로 children감싸서 반환해줍니다
useTodoState,useTodoDispatch를 통해 쉽게 state값과 dispatch함수를 가져올 수 있도록 만들어 두었습니다
사용하기
우선 Provier를 적용시켜줘야합니다 최상단 파일에서 만들어 두었던 TodoProvider를 감싸주시면 됩니다 예로 App.jsx에 감싸보겠습니다
1
import React from 'react';2
import Router from '../../../src/router';3
import TodoProvider from '../../../src/component';4
5
function App() {6
return (7
<TodoProvider>8
<Router />9
</TodoProvider>10
);11
}12
13
export default App;
1
function TodoPage(){2
const todoState = useTodoState()3
const dispatch = useTodoDispatch()4
5
const handleAddTodo = (todo) =>{6
dispatch({7
type:'ADD_TODO',8
todo:{9
id,10
content,11
isComplete12
}13
})14
}15
16
const handleDeleteTodo = (id) => {17
dispatch({18
type:'DELETE_TODO',19
todo:{20
id,21
content,22
isComplete23
}24
})25
}26
return(27
{todostate.map(todo => (28
<div>29
{todo.content}<button onClick={handleDeleteTodo}>삭제</button>30
</div>))}31
)32
}
이벤트마다 함수를 정의하고 dispatch에 type과 필요한 data를 넘겨주어 useReducer를 통해 state값을 변경할 수 있습니다