컴퍼넌트 상태를 업데이트 하기위해서 이전에는 useState
를 사용했는데 useReducer
를 사용해서 상태를 업데이트 하는 방법도 있다.
useState
설정하고 싶은 다음 상태를 직접 지정하는 방식으로 업데이트하지만
useReducer
는 action 이라는 객체를 기반으로 상태를 업데이트 한다. 여기서 action 객체는 업데이트 할때 참조하는 객체이다.
dispatch ({type: 'INCREMENT'})
type이라는 값을 사용해서 어떤 업데이트를 진행할건지 명시할 수 있고
dispatch({
type:'INCREMENT'
diff:4
})
업데이트 할 때 필요한 참조하고 싶은 다른 값을 넣을 수도 있다.
userReducer를 사용하면 상태 업데이트 로직을 컴포넌트 밖으로 분리가 가능하다. 심지어 다른 파일에 작성후 불러와서 사용이 가능하다. 여기서 reducer는 상태를 업데이트 하는 함수를 뜻한다.
function reducer(state, action){
switch(action.type){
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
reutnr state;
}
}
reducer
함수의 형식은 위와 같다.현재 상태와 액션 객체를 파라미터로 받아서 새로운 상태를 반환해주는 형태를 갖추고 있어야 한다.
전에 실습으로만든 Counter.js
를 통해서 연습해보자
import React, {useState} from "react";
function Counter() {
const [ number, setNumber] = useState(0);
const onIncrease = () =>{
setNumber(number + 1);
}
const onDecrease = () => {
setNumber(number - 1 );
}
return (
<>
<h1>{number}</h1>
<button onClick={onIncrease}>+1</button>
<button onClick={onDecrease}>-1</button>
</>
);
}
export default Counter;
현재 Counter 컴포넌트의 상태의 업데이트는 useState를 이용해서 진행했었다.
이것을 useReducer로 변경해보자.
function reducer(state, action){
switch (action.type) {
case'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1 ;
default:
throw new Error('Unhandled action');
}
}
const [number, dispatch] = useReducer(reducer, 0);
const onIncrease = () =>{
dispatch({
type: 'INCREMENT'
})
}
const onDecrease = () => {
dispatch({
type:'DECREMENT'
})
}
onIncrease는 1씩 더해지고, onDecrease는 1씩 감소한다.
결과를 확인해보자.
제대로 작동한다.
여기서 눈여겨 봐야할 점은 컴포넌트의 상태를 업데이트하는 로직이 컴포넌트의 바깥에 작성되어있다는 점이다.
이전의 useState의 경우는 컴포넌트의 내부에서 상태 업데이트를 하는 로직이 작성되었다.
import React, {useState, useReducer} from "react";
function reducer(state, action){
switch (action.type) {
case'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1 ;
default:
throw new Error('Unhandled action');
}
} // 요로코롬 바깥에 생성되어있다.
function Counter() {
const [number, dispatch] = useReducer(reducer, 0);
const onIncrease = () =>{
dispatch({
type: 'INCREMENT'
})
}
const onDecrease = () => {
dispatch({
type:'DECREMENT'
})
}
return (
<>
<h1>{number}</h1>
<button onClick={onIncrease}>+1</button>
<button onClick={onDecrease}>-1</button>
</>
);
}
export default Counter;