React의 핵심 훅: useReducer 파해치기!

chaen·2024년 4월 16일

REACT / NEXT.js

목록 보기
11/22
post-thumbnail

❓ useReducer란?

컴포넌트 내부에 새로운 State를 생성하는 React Hook 입니다. 모든 useStateuseReducer로 대체 가능합니다. useReducer는 해당 기능에 더불어 상태 관리 코드를 컴포넌트 외부로 분리할 수 있습니다.

 function reducer(){
   // 외부로 분리 가능
 }
function App() {
  const [todos, dispatch] = useReducer(reducer);
  //...
}

기존에 useState 의 경우 컴포넌트 안에서만 기능할 수 있다보니 다른 컴포넌트에서 사용하려면 해당 요소를 매개변수로 넘겨줘야 해서 코드가 점점 길어지고 복잡해지는 사태가 발생하였습니다. 따라서 이러한 상태 관리 코드를 외부의 별도의 함수로써 분리하고자 useReducer 를 사용하게 되었습니다.

💻 useReducer 사용해보기

먼저 간단한 실습을 위해 App 컴포넌트를 생성하고 Reducer 컴포넌트를 반환하도록 합니다.

// App.jsx
const App = () => {
  return (
    <Reducer />
    );
}

이후 Reducer 컴포넌트에서 간단한 카운터를 생성합니다.
useReducer 함수의 dispatch의 경우, 발송하다, 급송하다라는 뜻으로 상태 변화가 있어야 한다는 사실을 알리는, 발송하는 함수입니다.
그래서 컴포넌트 내부에서 dispatch를 호출하면, useReducer가 실제로 실행할 함수를 호출하게 횝니다.

import { useReducer } from "react";

const Reducer = () => {
  // reducer : 호출하여 실제로 실행할 함수
  // 0 : 초기값
  const [ state, dispatch ] = useReducer(reducer, 0);
  
  return (
  	<div>
      <h1>{state}</h1>
      <button>+</button>
    </div>
  );
};

export default Exam;

따라서 Reducer 함수 위에 실제로 실행할 함수 reducer를 만들어 줍니다.
또한 화면이 변화해야 하므로 클릭을 하면 호출될 함수인 onClickPlus를 만들고, 그 안에서 dispatch를 호출합니다.
dispatch의 인수로는 상태가 어떻게 변화되길 원하는지에 대한 정보가 들어 있는데, 이때 전달되는 객체를 액션 객체라고 하고 아래와 같이 타입(어떻게)과 데이터(얼마나) 등을 적습니다.

이후 해당 액션 객체는 reducer 함수의 매개변수 action 으로 전달되는데, 아래와 같이 현재 상태인 stateactiondata를 사용하여 값을 수정합니다. action의 타입이 "INCREASE"라는 말은 결국 상태의 변화가 일어났다는 뜻이므로 이렇게 설정 가능한 것입니다.

function reducer(state, action) {
  if(action.type === "INCREASE" {
     return state + action.data;
     }
}

const Reducer = () => {
  const [ state, dispatch ] = useReducer(reducer, 0);
  
  const onClickPlus = () => {
    dispatch({
     type: "INCREASE",
   	 data: 1,
    });
  }
  
  return (
  	<div>
      <h1>{state}</h1>
      <button onClick={onClickPlus}>+</button>
    </div>
  );
};

💻 새로운 함수 만들기

이어서 - 버튼도 만들어보겠습니다.
마찬가지로 버튼을 만들고 마이너스 암수를 호출한 후 조건문에 따라 상태를 변화시킵니다.
이때, 경우의 수가 많아질 경우 if문 보다 일반적으로 case를 사용하여 처리합니다.

function reducer(state, action) {
  switch(action.type){
    case 'INCREASE': return state + action.data;
    case 'DECREASE' : return state - action.data;
    default : return state; // 아무 변화도 x
  }   
}

const Reducer = () => {
  const [ state, dispatch ] = useReducer(reducer, 0);
  
  const onClickMinus = () => {
  dispatch({
    type: "DECREASE",
    data: 1,
  });
};
  
  return (
  	<div>
      <h1>{state}</h1>
      <button onClick={onClickMinus}>+</button>
    </div>
  );
};

보통, 이러한 카운터 앱은 사실 useState 로도 충분합니다. 하지만 링크와 같이 객체 데이터를 주고 받는 경우에는 함수가 복잡해지므로 이럴 때 useReducer 를 선택하여 사용하곤 합니다.


🔗참고 자료
한 입 크기로 잘라먹는 리액트

0개의 댓글