⚙️Frontend/REACT

[React] useReducer

soonybutter 2025. 5. 26. 17:12
728x90


 

 

 

React에서 '상태관리'에 사용되는 hook에는 useState와 useReducer가 있다.

useState는 간단한 상태관리를 위해 사용되지만,

복잡한 로직이 있는 경우에는 useReducer를 사용하는 것이 더 구조적이고 관리하기 쉽다. 

 

 useReducer의 개념과 적용한 예시 코드를 정리해보자 ! 

 


 

💡useReducer 란?

useReducer 는 상태(state)의 변경 로직을 컴포넌트 밖으로 분리해줌으로써 보다 명확하게 관리하는 Hook이다.

 

컴포넌트 외부에 상태 관리 코드를 분리

ex.
function reducer(){
	//...
}

function App(){
	const [todos, dispatch] = useReducer(reducer);
    //...
}

 

 

 

기본적인 사용 형태

const [state, dispatch] = useReducer(reducer, initialState);

 

*

state: 현재 상태

dispatch: 액션을 발생시키는 함수 (상태변화 요청/ 상태변화가 있어야하는 사실을 알림)

reducer: 상태를 실제로 변화시키는 함수 (변환기)

initialState: 초기값

*

 

 

위 useReducer은 두 가지를 리턴함

1. 현재 상태값(state)

2. 상태를 바꾸기 위한 dispatch 함수

 

 

dispatch함수를 호출함으로서,

1. action 객체가 reducer함수로 전달됨 .

2. reducer(state, action) 함수가 실행됨.

3. 새로운 상태값이 반환되고, 컴포넌트가 리렌더링됨.

 

 

 

 

 

 

ex.

버튼 클릭시 +1된 값을 화면에 렌더링하는 코드

function reducer(state, action) {
  switch (action.type) {
    case "INCREASE":
      return state + 1;
    default:
      return state;
  }
}

const [count, dispatch] = useReducer(reducer, 0);

const onClick = () => {
  dispatch({ type: "INCREASE" });
};

 

onClick() 는 dispatch({ type: "INCREASE" })를 호출하고,

  1. 이 액션이 reducer 함수로 전달됨
  2. reducer는 현재 state 값과 action을 기반으로 새로운 상태값을 계산
  3. 새로운 상태값이 useReducer에 의해 적용됨
  4. count 값이 갱신되고 컴포넌트가 리렌더링됨

 

dispatch()   useReducer()   reducer()

 

 

 


 

 

To do List 앱에 적용해보기

 

function reducer(state, action) {
  switch(action.type){
    case 'CREATE': 
      return [action.data, ...state];
    case 'UPDATE':
      return state.map((item)=>
        item.id === action.targetId
          ? {...item, isDone: !item.isDone}
          : item
      );
    case 'DELETE':
      return state.filter((item)=>item.id !== action.targetId);
    default: 
      return state;
  }
}

reducer 함수는 CREATE, UPDATE, DELETE라는 세 가지 액션을 처리한다.

  • CREATE: 새로운 할 일을 리스트에 추가
  • UPDATE: 특정 항목의 완료 여부를 토글
  • DELETE: 특정 할 일을 삭제

 

 

App 컴포넌트에서는 이 reducer를 다음과 같이 사용한다.

const [todos, dispatch] = useReducer(reducer, mockData);

 

 

 

const onCreate = (content) => {
  dispatch({
    type: "CREATE",
    data: {
      id: idRef.current++,
      isDone: false,
      content: content,
      date: new Date().getTime(),
    },
  });
};

const onUpdate = (targetId) => {
  dispatch({ type: "UPDATE", targetId });
};

const onDelete = (targetId) => {
  dispatch({ type: "DELETE", targetId });
};

 

이처럼 useReducer를 활용하면 복잡한 상태 업데이트 로직을 명확하게 분리할 수 있어 유지보수나 디버깅이 쉬워진다.

 

 

 

 

 

 

💡 useReducer를 사용하며 느낀 점

  • 상태 업데이트 로직을 reducer로 분리하면서 코드 구조가 더 명확해졌다.
  • dispatch를 통해 상태 변경을 요청하는 방식은 마치 Redux처럼 행동하므로, 상태 관리 흐름을 체계적으로 만들 수 있다.
  • 특히 CREATE, UPDATE, DELETE 같은 명확한 액션 타입을 사용하니, 디버깅 시 콘솔에 출력되는 action 정보만 봐도 어떤 일이 일어났는지 쉽게 알 수 있었다.

 

 

 

 


 

💡 정리

  • useReducer는 복잡한 상태를 효율적으로 관리할 수 있게 해주는 Hook이다.
  • 상태 변화 로직을 한 곳에 모아두기 때문에 가독성이 좋고, 재사용성이 높다.
  • dispatch와 action을 통해 상태 관리 흐름을 보다 명확히 제어할 수 있다.

단순한 상태 변경은 useState, 로직이 복잡하거나 액션이 다양한 경우는 useReducer가 적합하다는 것을 체감할 수 있었다.

 

상태가 복잡한 컴포넌트를 구현하려고 하는데, 로직을 간단하고 명확하게 하고자 한다?

-> useReducer를 적극적으로 활용하자 ☺️

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

*Ref

https://ko.react.dev/reference/react/useReducer

 

useReducer – React

The library for web and native user interfaces

ko.react.dev

 

 

 

설명이 부족한 부분이나 피드백은 댓글로 남겨주세요!

감사합니다 ☺️

728x90