본문 바로가기
코딩 정보/React

[React] useReduce의 간략한 사용방법을 알아보자

by 꽁이꽁설꽁돌 2024. 7. 14.
728x90
반응형

목차

     

     

    useReducer란?

    리액트의 useReducer는 상태관리와 상태 업데이트를 다루는 리액트 훅 중 하나로 

    복잡한 로직의 상태관리를 하거나 여러 컴포넌트의 상태를 공유할 때 이용한다.

     

    useState와 유사하나 더 구조적으로 꼭 사용해야 하는 것은 아니지만 필요할 때 선택적으로 이용할 수 있다.

     

     

     

    간략한 용어 정리

    • state -> 현재 상태
    • dispatch -> 상태 변경 시 필요한 정보를 전달하는 함수
    • reducer -> dispatch를 확인해서 state를 변경해 주는 함수
    • initial state -> state에 전달할 초기값

     

    예를 통해 알아보는 사용방법

    1. dispatch 만들어 주기

    shoppingCartreducer라는 상태 변경 함수를 첫번째 인자로 주고 두번째 인자로는 초기값을 전달해 준다.

      // action에 전달될 함수와 초기값 설정
      const [shoppingCartState, shoppingCartDispatch] = useReducer(
        shoppingCartReducer,
        {
          items: [],
        }
      );
      
      
      
      // 인수: 최신 state와 action(업데이트를 위한 정보를 가지고 있는 객체)
      //reducer는 항상 최신 상태 반환한다.
      function shoppingCartReducer(state, action) {
    
    
      return state;
    }

     

     

    2. action에 전달될 함수 만들어 주기

    action에 전달될 함수의 종류와 전달 인자를 setDispatch를 통해 설정해준다.

    function handleAddItemToCart(id) {
        shoppingCartDispatch({
          //각각의 action을 구분하기 위함
          type: "ADD_ITEM",
          payload: id, //전달 인자 설정
        });
        // -> action 매개 변수로 전달
      }
    
    
    function handleUpdateCartItemQuantity(productId, amount) {
        shoppingCartDispatch({
          type: "UPDATE_ITEM",
          payload: { productId, amount },
        });
    
      }

     

     

    3. 리듀서 함수에서 분기시켜 최신 상태 반영하기

    이런식으로 action.type을 if조건문으로 분기시켜 함수 타입별로 상태를 변경하고 최신상태를 반영할 수 있다.

    인자를 쓰고 싶다면 action.payload와 같이 사용해 주면 된다.

    function shoppingCartReducer(state, action) {
      if (action.type === "ADD_ITEM") {
        const updatedItems = [...state.items];
    
        const existingCartItemIndex = updatedItems.findIndex(
          (cartItem) => cartItem.id === action.payload
        );
        const existingCartItem = updatedItems[existingCartItemIndex];
    
        if (existingCartItem) {
          const updatedItem = {
            ...existingCartItem,
            quantity: existingCartItem.quantity + 1,
          };
          updatedItems[existingCartItemIndex] = updatedItem;
        } else {
          const product = DUMMY_PRODUCTS.find(
            (product) => product.id === action.payload
          );
          updatedItems.push({
            id: action.payload,
            name: product.title,
            price: product.price,
            quantity: 1,
          });
    
          return {
            //데이터 손실이 없도록 지난번 상태 복사
            ...state,
            items: updatedItems,
          };
        }
      }
      if (action.type === "UPDATE_ITEM") {
        const updatedItems = [...state.items];
        const updatedItemIndex = updatedItems.findIndex(
          (item) => item.id === action.payload.productId
        );
    
        const updatedItem = {
          ...updatedItems[updatedItemIndex],
        };
    
        updatedItem.quantity += action.payload.amount;
    
        if (updatedItem.quantity <= 0) {
          updatedItems.splice(updatedItemIndex, 1);
        } else {
          updatedItems[updatedItemIndex] = updatedItem;
        }
    
        return {
          ...state,
          items: updatedItems,
        };
      }
    
      return state;
    }

     

     

     

    반응형