React는 컴포넌트의 상태를 관리하기 위해 여러 가지 훅을 제공합니다. 그중 하나가 useReducer 훅으로, 상태를 복잡하게 업데이트할 필요가 있을 때 매우 유용한 훅입니다. useReducer는 상태를 처리하는 로직이 많거나, 여러 가지 상태를 관리해야 할 때, 특히 Redux와 같은 상태 관리 패턴과 유사한 방식으로 상태를 관리할 수 있도록 해줍니다.
목차
위의 목차를 클릭하면 해당 글로 자동 이동 합니다.
1. useReducer란?
useReducer 훅은 상태(state)와 액션(action)을 기반으로 상태를 업데이트하는 로직을 정의할 수 있는 React 훅입니다. 이는 상태 관리에서 useState보다 더 복잡한 상황에 유용합니다. 특히 상태가 여러 값을 포함하거나, 다양한 방식으로 상태가 변경되는 경우에 적합합니다.
const [state, dispatch] = useReducer(reducer, initialState);
- state: 현재 상태를 나타내는 변수입니다.
- dispatch: 상태를 업데이트하기 위해 호출하는 함수로, 특정 액션을 전달합니다.
- reducer: 상태를 업데이트하는 로직을 포함한 함수입니다. 이 함수는 현재 상태와 액션을 인자로 받아 새로운 상태를 반환합니다.
- initialState: 상태의 초기값입니다.
2. useReducer와 useState의 차이점
React에서 상태를 관리할 때 기본적으로 많이 사용하는 훅은 useState입니다. 하지만 useState는 상태가 단순하거나 적은 경우에 적합합니다. 반면, 상태가 복잡하고 다양한 액션에 따라 변할 필요가 있을 때는 useReducer가 더 나은 선택입니다.
useState | useReducer |
단순한 상태 관리에 적합 | 복잡한 상태 관리 및 다중 액션 처리에 적합 |
상태 업데이트 로직이 컴포넌트 내에 있음 | 상태 업데이트 로직이 reducer 함수에 집중됨 |
setState로 상태를 직접 업데이트 | dispatch로 액션을 통해 상태를 업데이트 |
3. useReducer 사용법
useReducer 훅은 reducer라는 함수에 모든 상태 업데이트 로직을 넣고, 상태를 변경할 때는 액션(action)을 전달합니다.
import React, { useReducer } from 'react';
// reducer 함수
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
return state;
}
}
function Counter() {
// useReducer 사용, 초기 상태는 { count: 0 }
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
<p>Count: {state.count}</p>
{/* dispatch로 액션을 전달하여 상태 업데이트 */}
<button onClick={() => dispatch({ type: 'increment' })}>+</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-</button>
</div>
);
}
export default Counter;
- Reducer 함수: reducer는 상태와 액션을 받아 상태를 업데이트하는 로직을 정의합니다. 위 예시에서는 increment와 decrement 액션에 따라 상태를 증가시키거나 감소시킵니다.
- useReducer: useReducer는 reducer 함수와 초기 상태를 받아 현재 상태와 dispatch 함수를 반환합니다.
- 액션 dispatch: dispatch 함수를 호출하여 특정 액션을 전달하면 reducer가 그에 맞는 상태 업데이트를 수행합니다.
4. 복잡한 상태 관리에서 useReducer 사용하기
useReducer는 복잡한 상태나 여러 액션을 처리해야 할 때 특히 유용합니다. 예를 들어, 폼 데이터를 관리하거나, 여러 상태를 동시에 업데이트해야 할 때 매우 효과적입니다.
import React, { useReducer } from 'react';
// reducer 함수
function formReducer(state, action) {
switch (action.type) {
case 'CHANGE_INPUT':
return {
...state,
[action.field]: action.value,
};
case 'RESET':
return {
name: '',
email: '',
};
default:
return state;
}
}
function Form() {
const [state, dispatch] = useReducer(formReducer, { name: '', email: '' });
const handleChange = (e) => {
dispatch({
type: 'CHANGE_INPUT',
field: e.target.name,
value: e.target.value,
});
};
const handleReset = () => {
dispatch({ type: 'RESET' });
};
return (
<div>
<input
name="name"
value={state.name}
onChange={handleChange}
placeholder="이름"
/>
<input
name="email"
value={state.email}
onChange={handleChange}
placeholder="이메일"
/>
<button onClick={handleReset}>초기화</button>
</div>
);
}
export default Form;
- Reducer 함수: 폼 데이터 관리에 필요한 CHANGE_INPUT과 RESET 액션을 처리합니다.
- 상태 업데이트: 인풋 값이 변경될 때 CHANGE_INPUT 액션을 디스패치(dispatch)하여 상태를 업데이트하며, 초기화 버튼을 클릭하면 RESET 액션을 통해 폼 상태를 초기화합니다.
useReducer 언제 사용할까?
- 복잡한 상태 관리: 상태가 단일 값이 아닌 여러 값을 포함하고 있을 때, useReducer는 상태 업데이트 로직을 깔끔하게 분리할 수 있습니다.
- 다중 액션 처리: 상태를 변경하는 액션이 여러 개 존재할 때, useReducer는 각 액션에 따른 상태 변경 로직을 명확하게 정의할 수 있습니다.
- 상태 업데이트 로직을 한 곳에서 관리: 상태 업데이트 로직이 컴포넌트 여러 곳에 퍼져있기보다, 리듀서(Reducer) 함수에서 한 곳에서 처리되기 때문에 코드가 더 깔끔해집니다.
- Redux와 비슷한 패턴 사용: useReducer는 Redux와 매우 유사한 상태 관리 패턴을 따릅니다. 만약 Redux를 사용할 필요는 없지만, 비슷한 구조가 필요하다면 useReducer가 좋은 선택이 될 수 있습니다.
추천글
'개발 공부 일지 > React' 카테고리의 다른 글
[React] 리액트 useMemo (성능 최적화) (1) | 2024.10.21 |
---|---|
[React] 리액트 생명 주기(Life Cycle) (3) | 2024.10.18 |
[React] 리액트 useRef란? (0) | 2024.10.15 |
[React] 리액트 Key - 리스트 렌더링 (0) | 2024.10.12 |
[React] 리액트 Router - 파라미터 & 쿼리 (0) | 2024.10.10 |