ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ React ] 리덕스 미들웨어 - Redux Thunk
    TIL 2024. 2. 20. 22:46
    728x90

    이미지 출처 :  Understanding Redux Thunk (morioh.com)

     

     

     

    리덕스 미들웨어란?

    이미지 출처 : 벨로퍼트 모던 리액트 깃북

     

    리덕스에서 dispatch를 하면 action이 reducer로 전달되고, reducer는 새로운 state를 반환한다. 

    근데 미들웨어를 사용해 이 과정의 중간에 우리가 하고 싶은 작업을 넣을 수 있다.

    ex) counter 프로그램에서 +1 버튼을 클릭시, 3초를 기다렸다가 +1이 구현되도록하기.

     

    보통 리덕스 미들웨어를 사용하는 이유는 서버와의 통신을 위해 사용하는 것이 대부분이고, 그 중에서도 많이

    사용하는 리덕스 미들웨어가 바로 Redux-thunk 라는 것이다.

     

    thunk를 사용하면 우리가 dispatch를 할때 객체가 아닌 함수를 dispatch 할 수 있게 해준다.

    dispatch(함수) → 함수실행 → 함수안에서 dispatch(객체)

     

    ReduxToolKit 에서는 createAsyncThunk 라는 API를 통해 thunk 함수를 생성할 수 있다.

    이 API는 함수이며, 1번째 인자에는 Action Value, 2번째 인자에는 함수가 들어간다.

    // __가 함수 이름에 붙는 이유는 이 함수가 thunk 함수라는 것을 표시하기 위한 
    // 개인의 convention 입니다. 함수의 이름은 본인이 편한 이름으로 명명하세요.
    
    export const __addNumber = createAsyncThunk(
    	"ADD_NUMBER_WAIT",
    	(payload, thunkAPI)=>{},
    );

     

    1번째 인자 (payload) = 이 thunk 함수가 외부에서 사용되었을 때 넣은 값을 여기에서 조회 가능.

    2번째 인자 = thunk가 제공하는 여러가지 API 기능들이 담긴 객체를 꺼낼 수 있다.

     

    그럼 addNumber를 클릭시 3초간 기다리는 thunk 함수를 예시로 만들어보자.

    // src/redux/modules/counterSlice.js
    
    import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
    
    export const __addNumber = createAsyncThunk(
    	// 첫번째 인자 : action value
      "addNumber", 
    	// 두번째 인자 : 콜백함수 
      (payload, thunkAPI) => {
        setTimeout(() => {
          thunkAPI.dispatch(addNumber(payload));
        }, 3000);
      }
    );
    
    const initialState = {
      number: 0,
    };
    
    const counterSlice = createSlice({
      name: "counter",
      initialState,
      reducers: {
        addNumber: (state, action) => {
          state.number = state.number + action.payload;
        },
    
        minusNumber: (state, action) => {
          state.number = state.number - action.payload;
        },
      },
    });
    
    
    export const { addNumber, minusNumber } = counterSlice.actions;
    export default counterSlice.reducer;

     

    이제 새로 만든 thunk 함수 __addNumber 를 App.jsx에 적용해보자.

     

    // src/App.jsx
    
    import React from "react";
    import { useState } from "react";
    import { useDispatch, useSelector } from "react-redux";
    import { minusNumber, __addNumber } from "./redux/modules/counterSlice";
    
    const App = () => {
      const dispatch = useDispatch();
      const [number, setNumber] = useState(0);
      const globalNumber = useSelector((state) => state.counter.number);
    
      const onChangeHandler = (evnet) => {
        const { value } = evnet.target;
        setNumber(+value);
      };
    
      // thunk 함수를 디스패치한다. payload는 thunk함수에 넣어주면,
      // 리덕스 모듈에서 payload로 받을 수 있다.
      const onClickAddNumberHandler = () => {
        dispatch(__addNumber(number));
      };
    
      const onClickMinusNumberHandler = () => {
        dispatch(minusNumber(number));
      };
    
      return (
        <div>
          <div>{globalNumber}</div>
          <input type="number" onChange={onChangeHandler} />
          <button onClick={onClickAddNumberHandler}>더하기</button>
          <button onClick={onClickMinusNumberHandler}>빼기</button>
        </div>
      );
    };
    
    export default App;

     

    새롭게 업데이트한 onClickAddNumberHandler 를 클릭하면 우리가 설정한 3초뒤에 숫자가 +1이 되는 것을 볼 수 있다.

     

    정리

    - 리덕스 미드웨어를 사용하면, 액션이 리듀서로 전달되기 전, 중간에 어떠한 작업을 추가 가능하다.
    - Thunk를 사용하면, 객체가 아닌 함수를 dispatch 할 수 있게 해준다.
    - 리덕스 툴킷에서 Thunk 함수 생성 = createAsyncThunk
    - createAsyncThunk( ) 의 1번째 인자 = action value, 2번째 인자 = 함수 가 들어간다.
    - 2번째로 들어가는 함수에서 2개의 인자를 꺼내 사용할 수 있는데, 1번째 인자는 컴포넌트에서 보내준 payload,
      2번째 인자는 thunk에서 제공하는 여러가지 기능이다. 
    728x90
Designed by Tistory.