aotoyae

[React] Redux Thunk : 미들웨어 본문

React

[React] Redux Thunk : 미들웨어

aotoyae 2024. 2. 19. 20:16

 

 

💡 미들웨어에 대해 알아보자.

 

미들웨어가 없을 때 ➡️ 액션 - 리듀서 - 스토어

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

여기서 미들웨어를 사용하면 이 과정 사이에 우리가 하고 싶은 작업들을 넣을 수 있다.

 

만약 카운터 프로그램에서 버튼을 클릭했을 바로 1 을 더하지 않고,

3초를 기다렸다가 1이 더해지게 구현하려면 미들웨어를 빼놓을 수 없다.

 

dispatch 가 되자마자 바로 action 이 리듀서로 달려가 새로운 state 를 반환하기 때문

즉, 여기서 "3초를 기다리는 작업" 을 미들웨어가 해주는 것이다.

 

보통 리덕스 미들웨어는 서버와의 통신을 위해 사용한다!

그 중 많이 사용되는 것이 Redux-thunk, saga

 

 

💡 Thunk 에 대해 알아보자

 

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

dispatch(객체) 가 아닌 dispatch(함수) 를 할 수 있게 된다.

 

따라서 중간에 우리가 원하는 작업을 함수를 통해 넣을 수 있고, 그것이 중간에 실행되는 것!

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

toolkit 에 내장되어 있다.

 

 

💡 Thunk 를 써보자! 3초 뒤에 숫자가 더해지게!

thunk 함수를 생성하면서 이름과 함수를 작성할 수 있고,

함수에선 2개의 인자를 꺼내 쓸 수 있는데, 받은 payload & thunk 에서 제공하는 여러가지 기능이다.

 

counterSlice.js

import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";

export const __addNumber = createAsyncThunk( // thunk 로 만든 addNumber
  "ADD_NUMBER_WAIT", // 이름
  (payload, thunkAPI) => { // 실행할 함수
    setTimeout(() => {
      thunkAPI.dispatch(addNumber(payload)); // 3초 뒤에 dispatch!
    }, 3000);
  }
);

export const __minusNumber = createAsyncThunk( // thunk 로 만든 minusNumber
  "MINUS_NUMBER_WAIT",
  (payload, thunkAPI) => {
    setTimeout(() => {
      thunkAPI.dispatch(minusNumber(payload)); // 3초 뒤에 dispatch!
    }, 3000);
  }
);


const initialState = {
  number: 0,
};

const counterSlice = createSlice({
  name: "counter",
  initialState,
  reducers: {
    addNumber: (state, action) => {
      state.number += action.payload;
    },
    minusNumber: (state, action) => {
      state.number -= action.payload;
    },
  },
});

export default counterSlice.reducer;
export const { addNumber, minusNumber } = counterSlice.actions;

 

App.jsx

import "./App.css";
import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { __addNumber, __minusNumber } from "./modules/counterSlice";

function App() {
  const globalNumber = useSelector((state) => state.counter.number);
  const [number, setNumber] = useState(0);

  const dispatch = useDispatch();

  const onClickAddNumber = () => {
    dispatch(__addNumber(+number)); // thunk로 만든 함수를 부른다.
  };

  const onClickMinusNumber = () => {
    dispatch(__minusNumber(+number)); // thunk로 만든 함수를 부른다.
  };

  return (
    <div>
      <h2>Thunk</h2>
      <h2>{globalNumber}</h2>
      <input type="number" onChange={(e) => setNumber(e.target.value)} />
      <button onClick={onClickAddNumber}>+</button>
      <button onClick={onClickMinusNumber}>-</button>
    </div>
  );
}

export default App;