아래의 로직과 같이 createContext로 Component를 생성한 후 Provider를 사용하면 children Component들은 모두 useContext로 전달 받은 value를 손쉽게 사용 가능하다.
정말 해당 Component만 사용하는 상태라면 useState를 사용하고 그 외에 여러곳에서 쓰일 여지가 있는 상태는 Context에 전달해서 관리해 보자 !
import { cerateContext, useState } from "react";
const contextData = {
state: { count: 0 },
action: {
setCount: () => {},
},
};
// createContext에서 기본적으로 가지고 있을 상태의 형식을 정의한다.
// 기본적으로 값을 가져다 사용할 수 있는 state와 값을 변환할 수 있는 action을 분류한다.
// 이 부분은 useReducer를 이용하면서 state -> useReducer.state // action -> dispatch로 대체 된다.
const TestContext = cerateContext(contextData);
const testProvider = ({ children }) => {
const [count, setCount] = useState(0);
// 해당 값을 useState로 정의해 주고 하위의 Component들이 사용할 수 있도록 value로 전달해 준다.
// 이때 state와 action으로 분류해서 사용한다.
const value = {
state: { count },
action: { setCount },
};
return <TestContext.Provider value={value}>{children}</TestContext.Provider>;
};
useReduer는 값을 더 많은 상황에서 다양하게 관리하는데 용의한 hook 입니다.
하지만 useReducer도 a에서 선언됐지만 e에서 값을 변환해야 하는 상황이 온다면 a→b→c→d→e 까지 전달해야만 사용할 수 있다는 단점이 있습니다.
이런 부분을 Context의 value로 전달함으로써 하위 Component들은 useContext로 간편하게 useReduer를 사용할 수 있습니다.
import { cerateContext, useReducer } from "react";
const data = {
count: 0,
};
const testReducer = (state, action) => {
switch (action.type) {
case "INCREASE":
return { count: state.count + 1 };
case "DECREASE":
return { count: state.count - 1 };
}
};
//action의 type에 따라서 state을 변화시킬 로직을 담는다.
const TestContext = cerateContext();
// Context는 기본값을 가지지 않는다.
const testProvider = ({ children }) => {
const [state, dispatch] = useReducer(testReducer, data);
// state는 위 예제의 useState의 state와 같으며 dispatch가 하는 역할은 useState에 setState와 같다고 할 수 있다.
// 하지만 useReducer를 이용해서 더 많은 State와 setState를 한곳에서 쉽게 관리 가능하다.
const value = {
state: { state },
action: { dispatch },
};
// value의 형식은 아까와 같지만 내부에 값은 다르다. state는 useReducer의 state , action은 dispatch로 Context의 value로 전달한다.
// Context의 value로 useReducer의 값을 전달함으로써 children Component들이 useReducer의 기능을 모두 사용할 수 있도록 한다.
return <TestContext.Provider value={value}>{children}</TestContext.Provider>;
};
// 기존 useReducer 첫번째 인자에 들어가는 상태관리 함수의 사용법
const baseballReducer = (state, action) => {
switch (action.type) {
case "FETCH_TEAM_LIST":
return { ...state, teamList: action.data.teamlist };
case "SELECT_TEAM":
return { ...state, selectedTeam: { name: action.name, image: action.image } };
default:
return state;
}
};
// 프로젝트 적용사항
// 각각의 action type들을 action 폴더에 변수로써 관리
const FETCH_TEAM_LIST = "FETCH_TEAM_LIST"
const SELECT_TEAM = "SELECT_TEAM"
const baseballReducer = (state, action) => {
switch (action.type) {
case FETCH_TEAM_LIST :
return { ...state, teamList: action.data.teamlist };
case SELECT_TEAM :
return { ...state, selectedTeam: { name: action.name, image: action.image } };
default:
return state;
}
};
//기본적인 사용법
dispatch({type : "INCREASE" , value : 5})
//함수로 분류해서 사용
const increaseCount = (value) => {
return {type : "INCREASE" , value : value};
}
dispatch(increaseCount(e.target.value));