Redux toolkit Thunk

With·2021년 9월 14일
0

Redux

목록 보기
2/2

module/todos.js

  • Redux toolkit 에서는 Thunk가 내장되어 있다.
  • createAsyncThunk 를 사용하고 redux-thunk와 비슷하게 썽크함수 내부에서 dispatch, getState()가 가능하다.
  • 특이한 점은, 이렇게 만들어진 썽크함수는 Slice 내에서 reducers가 아닌, extraReducers 에서 동작하며, 비동기처리 상태 3단계가 자동으로 각각 dispatch된다. (logger에도 각각 찍힌다 : pendingfullfilled) 즉, 한번의 dispatch(__loadTodos()) 호출로 대기, 이행, 실패 했을 때의 각각 후속작업을 진행 할 수 있다.
import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { todoApi } from "../api";

// thunk function
export const __loadTodos = createAsyncThunk(
  "todos/LOAD_TODOS", // 액션 이름을 지어줘야 한다.
  // getState와 dispatch 👇
  async (params, { getState, dispatch }) => {
    const { data } = await todoApi.loadTodos();
    return data;
  }
);

// Slice
const todoSlice = createSlice({
  name: "todos",
  initialState: {
    todos: {
      loading: true,
      error: {
        status: false,
        message: "",
      },
      data: [],
    },
  },
  reducers: {
    initTodos: (state) => (state.todos = { loading: true, data: [] }),
  },
  // redux-actions와 유사한듯 👇
  extraReducers: {
    [__loadTodos.pending]: (state) => {
      state.todos.loading = true;
    },
    [__loadTodos.fulfilled]: (state, { payload }) => {
      state.todos.loading = false;
      state.todos.data = payload;
    },
    [__loadTodos.rejected]: (state, { error }) => {
      console.log(error);
      state.todos.loading = false;
      state.todos.error.status = true;
      state.todos.error.message = error.message;
    },
  },
});

export const { initTodos } = todoSlice.actions;
export default todoSlice;

App.js

import { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { __loadTodos, initTodos } from "./module/todos";

function App() {
  const dispatch = useDispatch();
  const {
    loading,
    data: todos,
    error,
  } = useSelector((state) => state.todos.todos);


  useEffect(() => {
    dispatch(__loadTodos());
    return () => initTodos();
  }, []);

  if (loading) return <div>로딩중...</div>;

  if (error.status) return <div>{error.message}</div>;

  return (
    <div className="App">
      {todos.map((todo) => (
        <div key={todo.id}>{todo.title}</div>
      ))}
    </div>
  );
}

export default App;
profile
주니어 프론트엔드 개발자 입니다.

0개의 댓글