Redux Toolkit - thunk

moreas·2023년 2월 20일
0

팀 프로젝트

목록 보기
3/14
post-thumbnail

리덕스 툴킷에서는 비동기 작업을 어떻게 처리할까.

CreateAsyncThunk API

CreateAsyncThunk({action type}, {action creater가 호출됐을 때 실행할 함수})

// 파라미터 2개 필요

const asyncUpFetch = createAsyncThunk(
   'counterSlice/asyncUpFetch',
   async () => {
     const resp = await fetch('https://api.countapi.xyz/hit/opesaljkdfslkjfsadf.com/visits')
     const data = await resp.json();
     return data.value;
     // 리턴 값으로 store의 state변경

   }
 )



CreateAsyncThunk는 비동기 작업을 처리하는 action을 만들어준다.

asnyncUpFetch는 액션 크리에이터이기 때문에 타입이 있어야 한다.
액션이 실행됐을 때 처리되어야 하는 작업(서버 접속, 결과 가져오기)을 리턴하는 값을 두번째 파라미터의 함수로써 전달했다.





비동기 작업은 세 가지의 상태가 있다.

  • pending (대기)
  • fullfilled (성공)
  • rejected (오류 중단)

세 가지 상태별로 필요한 리듀서를 각각 정의한다.

const counterSlice = createSlice({
  name: 'counterSlice',
  initialState: {
    value: 0,
    status: 'Welcome',
  },
  reducers: {
    up: (state, action) => {
      state.value = state.value + action.payload;
    },
  },
  extraReducers: (builder) => {
    builder.addCase(asyncUpFetch.pending, (state, action) => {
      state.status = 'Loading';
    });
    builder.addCase(asyncUpFetch.fulfilled, (state, action) => {
      state.value = action.payload;
      state.status = 'complete';
    });
    builder.addCase(asyncUpFetch.rejected, (state, action) => {
      state.status = 'fail';
    });
  },
});

동기적인 액션은 reducers (action creacter를 자동으로 생성)
비동기 작업은 extraReducers 사용 (action creater 자동 생성 X)

그냥 이 문법 자체를 외우고 사용하면 될 것 같다.




전체 코드

  • counterSlice.js
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';

const asyncUpFetch = createAsyncThunk('counterSlice/asyncUpFetch', async () => {
  const resp = await fetch(
    'https://api.countapi.xyz/hit/opesaljkdfslkjfsadf.com/visits'
  );
  const data = await resp.json();
  return data.value;
});
//

const counterSlice = createSlice({
  name: 'counterSlice',
  initialState: {
    value: 0,
    status: 'Welcome',
  },
  reducers: {
  // 동기적인 액션
    up: (state, action) => {
      state.value = state.value + action.payload;
    },
  },
  extraReducers: (builder) => {
  // 비동기 작업
    builder.addCase(asyncUpFetch.pending, (state, action) => {
      state.status = 'Loading';
    });
    builder.addCase(asyncUpFetch.fulfilled, (state, action) => {
      state.value = action.payload;
      state.status = 'complete';
    });
    builder.addCase(asyncUpFetch.rejected, (state, action) => {
      state.status = 'fail';
    });
  },
});
export default counterSlice;
export const { up, set } = counterSlice.actions;
export { asyncUp, asyncUpFetch };
  • store.js
import {configureStore} from '@reduxjs/toolkit';
import counterSlice from './counterSlice';
const store = configureStore({
  reducer:{
    counter:counterSlice.reducer
  }
});
export default store;
  • App.js
import React from 'react';
import { createStore } from 'redux';
import { Provider, useSelector, useDispatch } from 'react-redux';
import store from './store';
import { up } from './counterSlice';
import { asyncUpFetch } from './counterSlice';

function Counter() {
  const dispatch = useDispatch();
  const count = useSelector((state) => {
    return state.counter.value;
  });
  const status = useSelector((state) => {
    return state.counter.status;
  });
  return (
    <div>
      <button
        onClick={() => {
          dispatch(up(2));
        }}
      >
        +
      </button>

      <button
        onClick={() => {
          dispatch(asyncUpFetch());
        }}
      >
        + async fetch
      </button>
      <br />

      <div>
        {count} | {status}
      </div>
    </div>
  );
}
export default function App() {
  return (
    <Provider store={store}>
      <div>
        <Counter></Counter>
      </div>
    </Provider>
  );
}




정리

  • createAsyncThunk은 비동기작업을 처리하는 action creator를 만든다.
    - action creator는 아래와 같이 3가지 상태를 갖는다.
    - action creator.pending는 대기상태.
    - action creator.fulfilled 는 완료 상태.
    - action creator.rejected는 오류 상태.
  • thunk는 각각의 상태에 따른 reducer를 체계적으로 작성할 수 있도록 유도한다.
  • thunk를 처리할 때는 extraReducers를 사용한다.

근데 아무리 봐도 코드의 양이.. 양 계산 잘못해서 미친듯이 불어난 미역같다.
간단한 로직이 이 정도인데 실제 개발에선 어떻게 사용될지 궁금하기도 하고 두렵기도 하고 그렇다.


참고 자료

생활코딩 redux toolkit - thunk 를 이용해서 비동기 작업을 처리하는 방법

profile
Everything is connected 🐶 좀 더 나은 개발을 위해

0개의 댓글