1차 공부/React공부

thunk가 뭔데 도대체

공대탈출 2022. 12. 13. 16:30

안그래도 코로나 걸려서 정신이 없는데 json서버니 axios니 thunk니 나를 괴롭힌다.

머리에 들어오질 않고, 민들레 홀씨 퍼지는 것 마냥 날아가버려서 좀 정리해보려고한다.


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

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

 

만약 counter프로그램에서 더하기 버튼을 클릭했을 때 바로 +1을 더하지않고 3초를 기다렸다가 +1이 되도록 구현하려면 미들웨어를 사용하지 않고서는 구현할 수 없습니다. 왜냐하면 dispatch가 되자마자 바로 action이 리듀서로 달려가 새로운 state를 반환해버리기 때문입니다.

즉 여기서 '3초를 기다리는 작업'을 미들웨어가 해주는 것 입니다.

 

보통 우리가 리덕스 미들웨어를 사용하는 이유는 서버와의 통신을 위해서 사용하는 것이 대부분이고, 또한 그 중에서도 많이 사용되고 있는 리덕스 미들웨어는 redux-thunk라는 것이 있습니다.

 

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

즉 dispatch(객체)가 아니라 dispatch(함수)를 할 수 있게 되는 것이죠.

그래서 중간에 우리가 하고자하는 작업을 함수를 통해 넣을 수 있고, 그것이 중간에 실행이 되는 것입니다.

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

와같은 흐름으로 실행이 됩니다. 그리고 이 함수를 thunk 함수라고 부릅니다.


thunk함수를 만들어봅시다.

아래 순서대로 구현을 할 것입니다.

  1. 첫 thunk 함수 만들기
  2. extraReducer에 thunk 등록하기
  3. dispatch(thunk함수)하기
  4. 테스트

thunk 함수의 역할은 3초를 기다리는 것 입니다. 그리고 3초가 지나면 원래 하려고 했던 ADD_NUMBER을 해주는 것 까지가 thunk함수가 해야할 일 입니다.

 

툴킷에서는 createAsyncThunk라는 API를 사용해서 thunk함수를 생성할 수 있습니다.

이 API는 함수인데, 첫번째 인자에는 Action Value, 두번쨰 인자에는 함수가 들어갑니다.

이 함수에 우리가 하고 싶은 작업들을 구현하면 됩니다.

 

두번째 인자에 들어가는 함수에서도 인자를 꺼낼 수 있는데 첫번째 인자는 이 thunk함수가 외부에서 사용되었을 때 넣은 값을 여기에서 조회할 수 있고, 두번째 인자에서는 thunk가 제공하는 여러가지 API기능들이 담긴 객체를 꺼낼 수 있습니다.

 

//thunk함수는 createAsyncThunk라는 툴킷 API를 사용해서 생성합니다.
//__가 함수 이름에 붙는 이유는 이 함수가 thunk 함수라는 것을 표시하기위한
//개인의 convention입니다. 함수의 이름은 본인이 편한 이름으로 명하세요.

export const __addNumber = createAsyncThunk(
    "ADD_NUMBER_WAIT",
    (payload, thunkAPI)=>{},
};

 

첫자리엔 action value를 넣고 두번째는 함수를 넣어 thunk함수를 만들어본자.

함수안에는 setTimeout이라는 Web API를 이용해 3초를 기다리게하고 이후 thunkAPI안에있는 dispatch를 통해 우리가 원래 하려던 addNumber이라는 action creator을 넣었다.

//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;

payload는 사용자가 input에 입력한 더하거나 뺴고자하는 값입니다. 이런식으로 payload 값을 받아올 수 있습니다.

기존에는 addNumber이라는 action creator을 dispatch해주었다면, 이제는 __addNumber이라는 thunk함수를 dispatch해줍니다.

//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;

 

 

1. 리덕스 미들웨어를 사용하면, 액션이 리듀서로 전달되기전에 중간에 어떤 작업을 더 할 수 있다.

2. Thunk를 사용하면, 객체가 아닌 함수를 dispatch 할 수 있게 해준다. (thunk의 핵심)

3. 리덕스 툴킷에서 Thunk 함수를 생성할 때는 createAsyncThunk를 이용한다.

4. createAsyncThunk()의 첫번째 인자는 actionvalue, 두번쨰는 함수가 들어간다.

5. 두번째로 들어가는 함수에서 2개의 인자를 꺼내 사용할 수 있는데,

   첫번째 인자는 컴포넌트에서 보낸 payload이고, 두번째 인자는 thunk에서 제공하는 여러가지 기능이다.

 

dispatch : thunk 함수 안에서 dispatch를 할 때 사용

getState : thunk 함수 안에서 현재 리덕스 모듈의 state값을 사용하고 싶을 때 사용

 

 

 

 

 

 

 

 

 

 

 

 

 

'1차 공부 > React공부' 카테고리의 다른 글

스타일드 컴포넌트 공부  (1) 2023.01.02
Thunk 두번째  (0) 2022.12.13
Axios관련 더 알아보기  (0) 2022.12.11
Axios  (0) 2022.12.10
json server  (0) 2022.12.10