리액트에서 상태를 업데이트 하고 싶을 때는 흔히 useState
를 사용한다.
매우 편한 훅이고 잘사용하고 있지만 이외에도 다른 방법으로 상태를 변경할 수 있다.
바로 useReducer
이다
useReducer
를 사용하게 되면 컴포넌트의 상태 업데이트 로직을 분리할 수 있으며 상태 업데이트 로직을 바깥에 사용할 수 있고 혹은 다른 파일에서 작성 후 불러올 수도 있다.
위의 그림은 리듀서가 돌아가는 방법을 도식화 한 것이다.
reducer는 state 업데이트를 하는 역할
dispatch는 state 업데이트를 위한 요구
action은 state 업데이트 요구 내용 이다.
은행 업무를 볼 때 우리가 돈을 가져가서 통장에 입금해 달라고 요청하면 은행에서 우리의 계좌에 돈을 넣어준다.
즉
우리(dispatch)가 돈을 가져가서(payload) 통장에 입금해 달라고 요청하면(action) 은행에서(reducer) 우리의 계좌에 돈을 넣어 준다(state)
위와 같이 이해하면 쉽다.
우선 나는 4개의 박스를 true false를 이용해서 체크를 하는 함수를 구현할 것이다.
const initialState = {
total : false,
first : false,
second : false,
third : false
}
전체 박스와 1~3번째 박스를 만들었다.
const initialState = {
total : false,
first : false,
second : false,
third : false
}
const [check, dispatch] = useReducer(reducer, initialState)
다음과 같이 구성하였고 useReducer에 reducer라는 함수를 밑에서 만들어 줄 것이다.
const initialState = {
total : false,
first : false,
second : false,
third : false
}
const reducer = (state, action) => {}
const [check, dispatch] = useReducer(reducer, initialState)
아직은 비어있는 함수를 만들었다.
인자값으로는 state, action을 받았고 state는 기존의 상태를 action은 업데이트 함수를 받는 것이다.
const initialState = {
total : false,
first : false,
second : false,
third : false
}
const reducer = (state, action) => {}
const [check, dispatch] = useReducer(reducer, initialState)
return(
<div>
<div onClick={() => {dispatch({type:'total'})}}>
전체박스
</div>
<div onClick={() => {dispatch({type:'first'})}}>
1번박스
</div>
<div onClick={() => {dispatch({type:'second'})}}>
2번박스
</div>
<div onClick={() => {dispatch({type:'third'})}}>
3번박스
</div>
</div>
)
보통 reducer함수에서 조건을 줄 때 switch case문으로 작성을 한다.
const initialState = {
total : false,
first : false,
second : false,
third : false
}
const reducer = (state, action) => {
switch(action.type){
case 'total' :
if(!state.total){
return{
total: true,
first: true,
second: true,
third: true
}
} else {
return{
total: false,
first: false,
second: false,
third: false
}
}
case "first" : {
return{
...state,
total : false,
first: !state.first
}
}
}
}
const [check, dispatch] = useReducer(reducer, initialState)
return(
<div>
<div onClick={() => {dispatch({type:'total'})}}>
전체박스
</div>
<div onClick={() => {dispatch({type:'first'})}}>
1번박스
</div>
<div onClick={() => {dispatch({type:'second'})}}>
2번박스
</div>
<div onClick={() => {dispatch({type:'third'})}}>
3번박스
</div>
</div>
)
위와 같은 식으로 만들어주면된다.
이때 나는 전체를 누르면 모두 해제되거나 모두 선택되거나 하고 각각의 박스를 눌렀을 경우 전체박스는 해제가되도록 만들고 다른 상태는 기억하도록 만들어 둔 것이다.
payload란
dispatch({type:"어쩌구", payload:어쩌구})
로 사용하며 dispatch를 보낼 때 state에 줄 값을 정의해준다.
payload로 값을 보내주면
reducer에서 받을 수 있는데
const reducer = (state, action) => {
action.payload
}
위와 같이 받을 수 있다.
이렇게 받은 값을 state와 더하거나 가공해서 사용할 수 있다.