Redux-Thunk๐Ÿ’ก

redux thunk : ๋ฆฌ๋•์Šค์—์„œ ๋น„๋™๊ธฐ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋ฏธ๋“ค์›จ์–ด

๊ธฐ์กด ์•ก์…˜์ƒ์„ฑํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•  ๋•Œ์—๋Š” async, await๊ณผ ๊ฐ™์€ ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์—†์Œ

์—๋Ÿฌ์ฝ”๋“œ

export const fetchData = async () => {
  const response = await axios.get('url')
  return {
    type: 'FETCH_DATA',
    payload: response.data
  }
}

Error: action must be plain objects. Use custom middleware for async actions

์ด๋Ÿฐ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ์œ„ํ•ด redux-thunk๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ

๐Ÿงกredux-thunk์˜ ์ž‘๋™๋ฐฉ์‹

export const fetchData = () => {
  return async function(dispatch, getState) {
	  const response = await axios.get('url')
	  return {
	    type: 'FETCH_DATA',
	    payload: response.data
	  }
  }
}
  • ์•ก์…˜๊ฐ์ฒด ์ƒ์„ฑํ•จ์ˆ˜๋Š” ์ง์ ‘์ ์œผ๋กœ asyncํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ธฐ๋•Œ๋ฌธ์—, ์•ก์…˜๊ฐ์ฒด๋ฅผ ๋ฆฌํ„ดํ•˜๋Š” asyncํ•จ์ˆ˜๋ฅผ returnํ•˜๋„๋ก ํ•จ
  • ์ฆ‰, ๋น„๋™๊ธฐ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ํ•จ์ˆ˜
  • ์ธ์ž๋กœ dispatch์™€ getState๋ฅผ ๋ฐ›์•„ ํƒ€์ž…๊ฐ์ฒด๋ฅผ returnํ•˜๋Š” ๋Œ€์‹ , ๋ฐ”๋กœ dispathํ•  ์ˆ˜ ์žˆ์Œ

๐Ÿงกredux-toolkit์˜ slice์™€ redux-thunk ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๊ธฐ

โœจ์š”์ฒญ์„ ๋ณด๋‚ด๋Š” thunkํ•จ์ˆ˜ ์ƒ์„ฑ

createAsyncThunk๋กœ ์•ก์…˜ํƒ€์ž…์„ ์ง€์ •ํ•˜๊ณ , ๋น„๋™๊ธฐํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑ

const ํ•จ์ˆ˜์ด๋ฆ„ = createAsyncThunk(์•ก์…˜ํƒ€์ž…์ด๋ฆ„, ๋น„๋™๊ธฐํ•จ์ˆ˜);

jsonplaceholder์—์„œ ๊ฒŒ์‹œ๊ธ€ ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์Œ

  export const getPosts = createAsyncThunk("getPosts", async () => {
    const response = await axios.get(
      "https://jsonplaceholder.typicode.com/posts"
    );
    return response.data;
  });
  • ์œ„ thunkํ•จ์ˆ˜์—์„œ returnํ•œ ๊ฐ’์€ reducerํ•จ์ˆ˜ ๋‚ด์—์„œ action.payload๋กœ ๋ฐ›์•„์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ

โœจcreateSlice๋กœ reducer์ƒ์„ฑ

  1. reducer๋ฅผ ์ƒ์„ฑํ•  ๋•Œ createSlice์˜ reducers: ์˜ ๊ฐ’์€ ๋น„์›Œ์ฃผ๊ณ , extraReducers๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค

  2. ์•„๋ž˜ ์ƒํƒœ์— ๋”ฐ๋ผ state๊ฐ€ ์–ด๋–ป๊ฒŒ ๋ณ€ํ•  ์ง€ ์ง€์ •ํ•ด์ฃผ๋„๋ก ํ•จ

  • ์š”์ฒญ์„ ๋ณด๋‚ผ ๋•Œ (pending)
  • ์š”์ฒญ์ด ์„ฑ๊ณตํ–ˆ์„ ๋•Œ (fulfilled)
  • ์š”์ฒญ์ด ์‹คํŒจํ–ˆ์„ ๋•Œ (rejected)
  1. ์œ„์—์„œ ์ž‘์„ฑํ•œ thunkํ•จ์ˆ˜์—์„œ returnํ•œ ๊ฐ’์€ action.payload ๋‹ด๊ธฐ๊ฒŒ ๋จ. ์ด๋ฅผ ํ™œ์šฉํ•ด์„œ state์˜ ๊ฐ’์„ ์ง€์ •
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"
import axios from "axios"

const initialState = {
  entities: [],
  loading: false,
};

export const getPosts = createAsyncThunk("getPosts", async () => {
  const response = await axios.get(
    "https://jsonplaceholder.typicode.com/posts"
  );
  return response.data
});

export const postSlice = createSlice({
  name: "posts",
  initialState,
  reducers: {},
  extraReducers: {
    [getPosts.pending]: (state) => {
      state.loading = true
    },
    [getPosts.fulfilled]: (state, action) => {
      state.loading = false;
      state.entities = action.payload
    },
    [getPosts.rejected]: (state) => {
      state.loading = false;
    },
  },
});

export default postSlice.reducer
profile
ํ”„๋ก ํŠธ์—”๋“œ ๊ฐœ๋ฐœ์ž ์„ฑ์žฅ์ผ๊ธฐ ๐Ÿ’ญ

0๊ฐœ์˜ ๋Œ“๊ธ€