useReducer
: 다양한 컴포넌트의 state를 업데이트 할 때 사용하는 Hook
장점 : 컴포넌트 업데이트 로직을 컴포넌트 밖으로 분리할 수 있다. (재사용 가능)
리듀서는 새로운 상태를 만들 때 반드시 불변성을 지켜주어야 한다. (기존 state의 값을 변경하는 것이 아니라 새롭게 생성한다.)
리듀서 함수
function reducer(state, action)
첫 번째 인자
: 기존 상태 값 (state)
두 번째 인자
: 업데이트를 위해 필요한 정보를 담은 객체(action)
const { useReducer } = React;
function reducer(state, action) {
/* action에 전달 된 type에 따라 새로운 state를 갱신할 객체를 생성해서
리턴한다. (불변성 유지) */
switch(action.type) {
case 'INCREMENT' : // 증가 동작
return { value : state.value + 1 };
case 'DECREMENT' : // 감소 동작
return { value : state.value - 1 };
default : // 아무 타입도 해당하지 않을 경우 기존 state 반환
return state;
}
}
useReducer
const [state, dispatcher] = useReducer(reducer, { value : 0 });
첫 번째 인자
: 리듀서 함수 (reducer)
두 번째 인자
: 해당 리듀서의 기본 값 ({ value : 0 })
state
: 현재 상태
dispatcher
: 액션을 발생 시키는 함수이다.(dispatcher 라는 변수명을 지은 것이기 때문에 바꿀 수 있음)
function Counter() {
const [state, dispatcher] = useReducer(reducer, { value : 0 });
return (
<>
<h1>count : { state.value }</h1>
<button onClick={ () => dispatcher({ type : 'DECREMENT'}) }>-1</button>
<button onClick={ () => dispatcher({ type : 'INCREMENT'}) }>+1</button>
</>
);
}
리듀서를 활용해 input 입력 값 상태 관리
const { useReducer } = React;
function reducer(state, action) {
console.log(state);
console.log(action);
return {
...state,
[action.name] : action.value
};
}
function RegistForm() {
const [state, dispatch] = useReducer(reducer, {
name : '',
nickname : ''
});
console.log(state);
console.log(dispatch);
const { name, nickname } = state;
/* change 이벤트가 발생하면 reducer로 이벤트 발생 객체를 전달한다. */
const onChangeHandler = e => dispatch(e.target);
return (
<>
<label>이름 : </label>
<input type="text" name="name" value={name} onChange={ onChangeHandler }/><br/>
<label>닉네임 : </label>
<input type="text" name="nickname" value={nickname} onChange={ onChangeHandler } /><br/>
<h3>입력한 이름 : {name}</h3>
<h3>입력한 닉네임 : {nickname}</h3>
</>
);
}