본문 바로가기

React

[React] Thunk

Redux 미들웨어 

 

액션 -> (미들웨어) -> 리듀서 -> 스토어

리덕스에서 dispatch 를 하면 action이 리듀서로 전달되고, 리듀서는 새로운 state 를 반환한다. 근데 미들웨어를 사용하면 이 과정 사이에 우리가 하고싶은 작업들을 넣을 수 있음.

 

ex) 만약 counter 프로그램에서 더하기 버튼을 클릭했을 시, 바로 +1 을 더하지 않고 3초를 기다렸다가 +1 이 되도록 구현하려면 미들웨어를 사용하지 않고는 구현 불가능.

이는 dispatch가 되자마자 action이 리듀서로 달려가서 새로운 state를 반환해버리기 때문.

여기서 3초를 기다리는 작업 -> 미들웨어가 해주는 역할.

 

미들웨어를 사용하는 이유는 서버와의 통신을 위해서 사용하는 것이 대부분이고, 많이 사용되는 것은 Redux-thunk, saga 등이 있다.

 


Thunk

리덕스에서 가장 많이 사용하는 미들웨어 중 하나로, thunk를 사용하면 우리가 dispatch 할 때 객체가 아닌 함수를 dispatch 할 수 있게 해줌. 즉, dispatch(함수)를 할 수 있게 되는 것.

 

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

 

1. thunk 함수를 만들기 : createAsyncThunk
- reduxToolkit 내장 API

 

2. createSlice > extraReducer 에 thunk 등록

3. dispatch

4. 테스트

 

counter.js

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

// 2개의 input
// (1) 이름 : 의미는 크게 없음
// (2) 함수
// 청크 이름에는 언더바 두개가 들어감
export const __plusNumber = createAsyncThunk(
  "PLUS_NUMBER_WAIT",
  (payload, thunkAPI) => {
    // 수행하고 싶은 동작 : 3초를 기다리게 할 예정
    setTimeout(() => {
      thunkAPI.dispatch(plusNumber(payload));
    }, 3000);
  }
);

export const __minusNumber = createAsyncThunk(
  "MINUS_NUMBER_WAIT",
  (payload, thunkAPI) => {
    setTimeout(() => {
      thunkAPI.dispatch(minusNumber(payload));
    }, 3000);
  }
);

// 초기 상태 값

const initialState = {
  number: 0,
};

// action creator, reducer 둘 다 들어있음
const counterSlice = createSlice({
  name: "counter",
  initialState,
  reducers: {
    plusNumber: (state, action) => {
      state.number = state.number + action.payload;
    },
    minusNumber: (state, action) => {
      state.number = state.number - action.payload;
    },
  },
});

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

 

App.js

import logo from "./logo.svg";
import "./App.css";
import { useState } from "react";
import { useSelector } from "react-redux";
import { useDispatch } from "react-redux";
import { __plusNumber, __minusNumber } from "./modules/counter";

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

  const onPlusButtonClickHandler = () => {
    dispatch(__plusNumber(+number));
  };
  const onMinusButtonClickHandler = () => {
    dispatch(__minusNumber(+number));
  };

  return (
    <div>
      {globalnumber}
      <input type="number" onChange={(e) => setNumber(e.target.value)} />
      <br />
      <button onClick={onPlusButtonClickHandler}>+</button>
      <button onClick={onMinusButtonClickHandler}>-</button>
    </div>
  );
}

export default App;

 

 

 

 

'React' 카테고리의 다른 글

[React] React Query  (0) 2023.07.05
[React] custom hooks  (0) 2023.07.05
[React] instance 와 interceptor  (0) 2023.07.04
[React] Fetch 와 Axios  (0) 2023.07.04
[React] 비동기 통신 axios(patch)  (0) 2023.07.04