React

[React] useReducer

winter17 2024. 2. 5. 15:31

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

 

useReducer – React

The library for web and native user interfaces

react.dev

 

useReducer는 리액트에서 제공하는 훅 중 하나로, 컴포넌트의 상태와 상태를 업데이트하는 로직을 분리하여 관리할 수 있도록 도와주는 훅이다. 복잡한 상태 로직을 더 구조적으로 관리할 수 있다.

 


#Challenge: Bank Account

첫 시작(open account)
대출 5000(request a loan of 5000) -> 납부 후(pay loan)

 

import { useReducer } from "react";
import "./styles.css";

const initialState = {
  balance: 0,
  loan: 0,
  isActive: false
};
// 리듀서 함수 정의
function reducer(state, action) {
  if (!state.isActive && action.type !== "openAccount") return state;

  switch (action.type) {
    case "openAccount":
      return {
        ...state,
        balance: 500,
        isActive: true
      };
    case "deposit":
      return { ...state, balance: state.balance + action.payload };
    case "withdraw":
      return { ...state, balance: state.balance - action.payload };
    case "requestLoan":
      if (state.loan > 0) return state;
      return {
        ...state,
        loan: action.payload,
        balance: state.balance + action.payload
      };
    case "payLoan":
      return { ...state, loan: 0, balance: state.balance - state.loan };
    case "closeAccount":
      if (state.loan > 0 || state.balance !== 0) return state;
      return initialState;
    default:
      throw new Error("Unkown");
  }
}

export default function App() {
  // useReducer를 통해 상태와 리듀서를 연결 
  const [{ balance, loan, isActive }, dispatch] = useReducer(
    reducer,
    initialState
  );

  return (
    <div className="App">
      <h1>useReducer Bank Account</h1>
      <p>Balance: {balance}</p>
      <p>Loan: {loan}</p>

      <p>
        <button
          onClick={() => dispatch({ type: "openAccount" })}
          disabled={isActive}
        >
          Open account
        </button>
      </p>
      <p>
        <button
          onClick={() => dispatch({ type: "deposit", payload: 150 })}
          disabled={!isActive}
        >
          Deposit 150
        </button>
      </p>
      <p>
        <button
          onClick={() => dispatch({ type: "withdraw", payload: 50 })}
          disabled={!isActive}
        >
          Withdraw 50
        </button>
      </p>
      <p>
        <button
          onClick={() => dispatch({ type: "requestLoan", payload: 5000 })}
          disabled={!isActive}
        >
          Request a loan of 5000
        </button>
      </p>
      <p>
        <button
          onClick={() => dispatch({ type: "payLoan" })}
          disabled={!isActive}
        >
          Pay loan
        </button>
      </p>
      <p>
        <button
          onClick={() => dispatch({ type: "closeAccount" })}
          disabled={!isActive}
        >
          Close account
        </button>
      </p>
    </div>
  );
}

 

 

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

 

useReducer의 첫 번째 매개변수는 리듀서 함수이고, 두 번째 매개변수는 초기 상태이다. 

useReducer는 현재 상태와 dispatch 함수를 반환한다. dispatch함수는 액션을 전달하여 상태를 업데이트할 때 사용한다.

 

function reducer(state, action) {
	switch (action.type) {
    case "openAccount":
      return {
        ...state,
        balance: 500,
        isActive: true
      };
    case "deposit":
      return { ...state, balance: state.balance + action.payload };
    default:
      throw new Error("Unkown");
  }
}

 

reducer 함수에서는 액션의 타입에 따라 다른 동작을 수행하도록 정의된다. 액션은 상태를 어떻게 업데이트할지를 나타내며, 리듀서는 현재 상태와 액션을 받아 새로운 상태를 반환한다.

 

useReducer는 컴포넌트가 복잡한 상태 논리를 가질 때 유용하며, 특히 여러 액션이 상태를 변경할 때 좀 더 간결하게 관리할 수 있다.