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와의 차이점

  • useState
    • 단순한 상태 관리를 위해 사용
    • 하나의 상태 값과 상태를 변경할 수 있는 함수를 제공
  • useReducer
    • 복잡한 상태 로직, 여러 상태를 조작해야 하거나, 상태 변경 로직이 다양한 경우 사용
    • ex) 상태 업데이트가 단일 변수 이상일 때, 로직을 별도의 리듀서 함수로 분리함으로써 코드의 가독성과 유지보수성을 높일 수 있다.

 

 

✅ 사용

 

1. useReducer 불러오기

import { useReducer } from 'react';

 

 

 

2. reducer 함수 작성

function reducer(state, action) {
  // state를 계산할 코드
  
  return {
    // 계산된 state를 반환
  };  
}
  • reducer 함수
    : state가 어떻게 업데이트 되는지 지정하는 순수 함수
    • 리듀서 함수는 반드시 순수 함수여야 한다.
    • 현재 상태(state)와 액션(action)을 인수로 받아서 새로운 state를 반환한다.
      • action: reducer 함수에 전달되는 객체 ➡︎ 상태를 어떻게 변경할지를 나타내는 정보를 담고 있다.
        • type
          : 어떤 종류의 액션인지 나타낸다.

          • action 객체에서 가장 중요한 필드
          • 이 type 필드의 값에 따라 reducer가 어떻게 동작할지 결정된다.
        • payload (선택 사항)
          : 추가적인 데이터가 필요할 때, payload라는 필드를 사용해 전달
export default function TaskApp() {
  const [tasks, dispatch] = useReducer(
    tasksReducer,
    initialTasks
  );

  function handleAddTask(text) {
    dispatch({
      type: 'added',
      id: nextId++,
      text: text,
    });
  }

  function handleChangeTask(task) {
    dispatch({
      type: 'changed',
      task: task
    });
  }

  function handleDeleteTask(taskId) {
    dispatch({
      type: 'deleted',
      id: taskId
    });
  }

  return (
    <>
      <h1>Prague itinerary</h1>
      <AddTask
        onAddTask={handleAddTask}
      />
      <TaskList
        tasks={tasks}
        onChangeTask={handleChangeTask}
        onDeleteTask={handleDeleteTask}
      />
    </>
  );
}

 

 

 

3. useReducer 사용

const [state, dispatch] = useReducer(reducer, initialState, init?)
  • 매개변수
    • reducer
      : state가 어떻게 업데이트 되는지 지정하는 순수 함수
      • 리듀서 함수는 반드시 순수 함수여야 한다.
      • 현재 상태(state)와 액션(action)을 인수로 받아서 새로운 state를 반환한다.
    • initialState
      : 초기 state 값
      • 컴포넌트가 처음 렌더링될 때의 초기 상태
    • init
      : 초기 state를 반환하는 초기화 함수
      • 이 함수가 인수에 할당되지 않으면 초기 state는 initialState로 설정된다.
      • 할당되었다면 초기 state는 init(initialState)를 호출한 결과가 할당된다.
  • 반환값
    useReducer는 2개의 엘리먼트로 구성된 배열을 반환한다.
    1. 현재 state
      : 첫번째 렌더링에서의 state는 init(initialArg) 또는 initialArg로 설정된다.
      (init이 없을 경우 initialArg로 설정된다)
    2. dispatch 함수
      : state를 새로운 값으로 업데이트하고 리렌더링을 일으킨다.

 

 

 

예제 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