All'alba vincerò

At dawn, I will win!

React

[React] useReducer(): 복잡한 상태(state)를 처리하는 상태 관리 훅

나디아 Nadia 2024. 8. 23. 11:31

📌 useReducer()

: 복잡한 상태(state) 로직을 처리하는 상태 관리 훅

  • useState와 유사하지만, 상태(state) 업데이트 로직을 더 명확하게 분리하고 다양한 상태(state) 변화를 처리한다.
  • 현재 상태와 액션을 받아 새로운 상태를 반환하는 리듀서 함수를 사용한다.
    ➡︎ 상태 변화는 액션에 의해 일어나며, 이 액션은 리듀서 함수에 전달된다.
  • useReducer에서 사용하는 리듀서 함수는 순수해야 한다. 
    ➡︎ 사이드 이펙트 코드가 들어가면 안된다.
  • 사용
    • 상태(state) 변화가 복잡하고, 여러 가지 액션에 따라 다양한 상태 변경이 필요할 때
    • 상태(state)와 관련된 로직을 분리하여 관리하고 싶을 때
    • 리덕스(Redux)와 같은 상태 관리 패턴을 작은 컴포넌트 내에서 구현하고 싶을 때

 

 

useState vs useReducer 

특징 useState  useReducer
사용 목적 단순한 상태 관리 복잡한 상태 로직 관리, 여러 상태를 조작해야 할 때
제공 기능 하나의 상태 값과 상태를 변경할 수 있는 함수 제공 현재 상태와 dispatch 함수를 반환
상태 업데이트 방식 간단한 값 변경 상태 업데이트 로직을 별도의 리듀서 함수로 분리
사용 상황 - 단일 변수 상태 관리
- 간단한 값 변경
- 여러 상태 관리
- 상태 변경 로직이 복잡하거나 다양할 때
- 상태를 업데이트하는 코드 재사용이 필요한 경우
코드 가독성
유지보수성
간단한 상태 관리에서는 가독성이 좋음 리듀서로 로직을 분리함으로써
복잡한 로직 관리 시 가독성과 유지보수성 향상

 


 

✅ 사용

 

1. useReducer 불러오기

import { useReducer } from 'react';

 

 

 

2. reducer 함수 작성

function reducer(state, action) {
  // state를 계산할 코드
  
  return {
    // 계산된 state를 반환
  };  
}

 

reducer 함수
: state가 어떻게 업데이트 되는지 지정하는 순수 함수

  • 리듀서 함수는 반드시 순수 함수여야 한다.
  • 현재 상태(state)와 액션(action)을 인수로 받아서 새로운 state를 반환한다.
    • state: 현재 상태
    • action: 상태를 변경할 명령을 포함하는 객체
      • type: 어떤 종류의 액션인지 나타낸다.
        • action 객체에서 가장 중요한 필드
        • 이 type 필드의 값에 따라 reducer가 어떻게 동작할지 결정된다.
      • payload(선택): 상태 변경에 필요한 추가 데이터
function reducer(state, action) {
  switch (action.type) {
    case 'added':
      return [...state, { id: action.id, text: action.text }];
    case 'changed':
      return state.map((task) =>
        task.id === action.task.id ? action.task : task
      );
    case 'deleted':
      return state.filter((task) => task.id !== action.id);
    default:
      throw new Error(`Unhandled action type: ${action.type}`);
  }
}

 

 

 

3. useReducer 사용

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

 

 

반환값

  • state: 현재 state
    • 첫번째 렌더링에서의 state는 init(initialArg) 또는 initialArg로 설정된다.
      (init이 없을 경우 initialArg로 설정된다)
  • dispatch 함수: state를 업데이트하고 리렌더링을 일으키는 함수
    • dispatch에 액션 객체를 전달하여 상태를 변경한다.

 

매개변수

  • reducer: state가 어떻게 업데이트 되는지 지정하는 순수 함수
    • 리듀서 함수는 반드시 순수 함수여야 한다.
    • 현재 상태(state)와 액션(action)을 인수로 받아서 새로운 state를 반환한다.
  • initialState: 초기 state 값
    • 컴포넌트가 처음 렌더링될 때의 초기 상태
  • init: 초기 state를 반환하는 초기화 함수
    • 이 함수가 인수에 할당되지 않으면 초기 state는 initialState로 설정된다.
    • 할당되었다면 초기 state는 init(initialState)를 호출한 결과가 할당된다.
export default function Counter() {
  const initialState = { count: 0 };
  
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <h1>Count: {state.count}</h1>
      <button onClick={() => dispatch({ type: 'increment' })}>+1</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-1</button>
      <button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
    </div>
  );
}

 

 


 

예제 1. 카운터 컴포넌트

  • reducer 함수 작성
    • reducer 함수는 현재 상태와 액션을 받아서 새로운 상태를 반환한다.
    • action.type이 increment인 경우 상태의 count를 1 증가시키고, decrement인 경우 1 감소시킨다.
  • 초기 상태 설정
    • initialState는 컴포넌트가 처음 렌더링될 때 사용되는 초기 상태이다.
    • 여기서는 { count: 0 }으로 설정했다.
  • useReducer 사용
    • useReducer 훅을 사용하여 reducer 함수와 initialState를 전달한다.
    • state는 현재 상태를 나타내고, dispatch는 액션을 보낼 때 사용된다.
  • 컴포넌트 내에서 상태 관리
    • dispatch를 사용하여 상태를 변경할 수 있다.
    • dispatch 함수에 { type: 'increment' } 또는 { type: 'decrement' }를 전달하여 상태를 업데이트한다.
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 };
    case 'reset':
      return { count: action.payload };
    default:
      return state;
  }
}

// 초기 상태와 초기화 함수
const initialState = { count: 0 };

function Counter({ initialCount }) {
  // useReducer 사용
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
      <button onClick={() => dispatch({ type: 'reset', payload: initialCount })}>Reset</button>
    </div>
  );
}

export default Counter;

 


 

 

useReducer – React

The library for web and native user interfaces

ko.react.dev

 

 

state 로직을 reducer로 작성하기 – React

The library for web and native user interfaces

ko.react.dev