【React】ReduxToolkit에서 비동기 처리 구현

개요


  • Redux를 사용하여 비동기 처리를 구현할 때 ReduxThunk과 같은 middleware를 사용하는 경우가 많습니다.
  • 그러나 middleware를 사용하면 구현이 다소 어려워지는 경우도 많이 괴로운 장면도 있습니다

  • ReduxToolkit은 ReduxThunk가 내장되어있어 구현량 적게 Redux로 비동기 처리를 만들 수 있습니다.

    사전 준비



  • CreateReactApp에서 React 앱의 병아리를 만들어 둡니다
  • npx create-react-app redux-thunk-sample
    
  • 다음 명령으로 시작할 수 있습니다
  • yarn start
    # open http://localhost:3000
    

    ReduxToolkit을 사용한 비동기 처리 구현


  • 이번에는 Qiita의 API를 두드려 기사 일람을 취득해 보겠습니다

  • 라이브러리 추가


  • Redux 관련 라이브러리 설치
  • yarn add react-redux @reduxjs/toolkit
    

    통신 처리 작성


  • Qiita API를 두드리는 부분을 만듭니다

  • src/api/qiitaApi.js
    export async function getItems() {
      const res = await fetch('https://qiita.com/api/v2/items');
      const json = await res.json();
      if (!res.ok) throw new Error(json.message);
      return json;
    }
    
  • 이번 주가되는 Redux의 처리를 작성하는 파일을 작성합니다.

    src/store/qiitaSlice.js
    import { createSlice } from '@reduxjs/toolkit';
    import { getItems } from '../api/qiitaApi';
    
    // Slice
    export const qiitaSlice = createSlice({
      name: 'qiita',
      // stateの初期値を設定
      initialState: { loading: false, error: null, items: [] },
      reducers: {
        // 通信を開始した時に呼ぶ関数
        fetchStart(state, action) {
          state.loading = true;
          state.error = null;
        },
        // 通信が失敗した時に呼ぶ関数
        fetchFailure(state, action) {
          state.loading = false;
          state.error = action.payload;
        },
        // 通信が成功した時に呼ぶ関数
        fetchSuccess(state, action) {
          state.loading = false;
          state.error = null;
          state.items = action.payload;
        },
      },
    });
    
    // Actions
    export const { fetchStart, fetchFailure, fetchSuccess } = qiitaSlice.actions;
    
    // 外部からはこの関数を呼んでもらう
    export const fetchItems = () => async dispatch => {
      try {
        dispatch(fetchStart());
        dispatch(fetchSuccess(await getItems()));
      } catch (error) {
        dispatch(fetchFailure(error.stack));
      }
    };
    
    // Selectors
    export const selectQiita = ({ qiita }) => qiita;
    
    // Reducer(must be default export)
    export default qiitaSlice.reducer;
    
  • 통신 중인지 여부를 나타냅니다 loading , 오류 정보 넣기
  • 비동기가 아닌 경우는 error 에 정의한 함수를 외부로부터 dispatch 하고 있었습니다
  • 비동기 처리의 경우, 처리의 개시 및 종료시에 State를 갱신하고 싶습니다.
  • 그래서 외부에서 직접.


  • 기사 목록을 표시하는 구성 요소 만들기


  • Redux 처리를 호출하여 얻은 정보를 표시하는 구성 요소를 만듭니다.

    src/components/QiitaItems.js
    import React, { useEffect } from 'react';
    import { useSelector, useDispatch } from 'react-redux';
    import { selectQiita, fetchItems } from '../store/qiitaSlice';
    
    function QiitaItems() {
      const dispatch = useDispatch();
      const { loading, error, items } = useSelector(selectQiita);
    
      useEffect(() => {
        // fetchItemsを実行
        dispatch(fetchItems());
      }, [dispatch]);
    
      if (loading) return <p>...loading</p>;
      if (error) return <p>{error}</p>;
    
      return items.map(item => (
        <div key={item.id}>
          <h2><a href={item.url}>{item.title}</a></h2>
          <p>{item.created_at} by {item.user.id}</p>
        </div>
      ));
    }
    
    export default QiitaItems;
    
  • useEffect에서 items
  • 통신 중에는 reducers로 표시되어 완료하면 기사의 정보가 표시되도록 하고 있습니다.

    Redux 설정


  • Redux를 사용하기위한 설정을 넣으십시오
  • App.js 수정

  • src/App.js
    import React from 'react';
    import { Provider } from 'react-redux';
    import { store } from './store';
    import QiitaItems from './components/QiitaItems';
    
    function App() {
      return (
        <Provider store={store}>
          <QiitaItems />
        </Provider>
      );
    }
    
    export default App;
    
  • Store 만들기

  • src/store/index.js
    import { configureStore } from '@reduxjs/toolkit';
    import qiitaReducer from './qiitaSlice';
    
    export const store = configureStore({
      reducer: {
        qiita: qiitaReducer,
      },
    });
    

    동작 확인


  • 잘 작동한다면 다음과 같아야합니다



  • 요약


  • ReduxToolkit을 사용하면 통신 처리도 복잡성을 느끼지 않고 구현할 수있었습니다.
  • 구현 된 코드도 이해하기 쉽고 좋네요
  • 좋은 웹페이지 즐겨찾기