
상태관리 로직이 복잡할 때 useState 대체품으로 사용
현재 상태와 액션을 받아 새로운 상태를 반환하는 리듀서(reducer) 함수를 통해 상태를 관리
useReducer는 리듀스 함수와 초기 상태를 인자로 받아 상태값과 디스패치 함수를 반환
- 액션 : 상태를 변경하기 위한 정보가 담긴 객체로, 일반적으로 type 프로퍼티를 가지고 있으며, 필요에 따라 데이터를 포함할 수 있음
- 디스패치 함수: 액션을 리듀서로 전달해서 상태를 업데이트 하는 함수
const Counter = () => {
const [count, setCount] = useState(0);
const changeCount = (e) => setCount(count + Number(e.target.innerText));
return (
<>
<div>
현재 카운터 값은 <b>{count} 입니다.</b>
</div>
<div>
<button onClick={changeCount}>+1</button>
</div>
<div>
<button onClick={changeCount}>-1</button>
</div>
</>
);
};
setCount(count + Number(e.target.innerText));
버튼 안의 내용(innerText)를 Number() 이용해서 숫자로 바꿔줌
버튼의 내용이 숫자로 변환가능하기 때문에 하나의 핸들러 함수로 구현이 가능한 것
버튼의 내용이 문자열인 경우 ➡️ 숫자로 변환할 수 없음 ➡️ 핸들러 함수를 따로 작성해야 함
리듀스 함수 생성
function reducer(state, action) {
switch (action.type) {
case "INCREMENT":
return { count: state.count + 1 };
case "DECREMENT":
return { count: state.count - 1 };
default:
return state;
}
}
state:현재 상태변수
action: 상태변수 변경에 필요한 조건과 값 (호출 시 전달되는 값)
const Counter = () => {
const [state, disptch] = useReducer(reducer, { count: 0 });
return (
<>
<div>
현재 카운터 값은 <b>{state.count} 입니다.</b></div>
<div>
<button onClick={() => disptch({ type: "INCREMENT" })}>하나 더하기</button>
</div>
<div>
<button onClick={() => disptch({ type: "DECREMENT" })}>하나 빼기</button>
</div>
</>
);
};
useReducer(reducer, { count: 0 }) 리듀서 함수와 초기 상태를 인자로 받음
const [state, disptch] 상태값과 디스패치 함수 반환
onClick={() => disptch({ type: "INCREMENT" })}
액션을 리듀서로 전달해서 상태를 업데이트
const Info = () => {
const [name, setName] = useState("");
const [nickname, setNickname] = useState("");
const changeName = (e) => setName(e.target.value);
const changeNickname = (e) => setNickname(e.target.value);
return (
<>
<div>
<p>이름:{name} </p>
<p>별명: {nickname}</p>
</div>
<div>
<p>
이름: <input type="text" value={name} onChange={changeName} />
</p>
<p>
별명: <input type="text" value={nickname} onChange={changeNickname} />
</p>
</div>
</>
);
};
리듀서 함수 정의

action = { type: 변경할 상태변수, value: 변경할 값 }
액션의 구조는 내가 지정함
dispatch() 함수를 호출할 때 action 값을 설정해서 전달
const Info = () => {
const [state,dispatch]=useReducer(reducer,{name:"",nickname:""});
return (
<>
<div>
<p>이름:{state.name} </p>
<p>별명: {state.nickname}</p>
</div>
<div>
<p>
이름: <input type="text" value={state.name} onChange={(e)=>dispatch({type:"name", value:e.target.value})} />
</p>
<p>
별명: <input type="text" value={state.nickname} onChange={(e)=>dispatch({type:"nickname", value:e.target.value})} />
</p>
</div>
</>
);
};
const [state,dispatch]=useReducer(reducer,{name:"",nickname:""}); 리듀서함수와 초기 상태를 인자로 받아서 상태값과 디스패치 함수 반환
onChange={(e)=>dispatch({type:"name", value:e.target.value})}
이벤트 객체를 인자로 받고, 디스패치 함수 호출
action값 설정 type:"name" 으로 지정, value: 이벤트 객체의 value

onChange 함수에 disaptch 함수를 각각 적용해주었는데 name 속성을 추가하면 changeValue 함수를 이용해 한번에 관리할 수 있음

const reducer = (state, action) => {
/*
case "name":
return { ...state, name: action.value };
case "nickname":
return { ...state, nickname: action.value };
default:
return state;
}*/
return {...state,[action.type]:action.value};
};
간소화된 코드
