サイト名変更・お引越しのお知らせ

Redux Toolkitを使ってReduxをシンプルに使う方法を解説

Reduxは学習コストも高く、記述も多いのでその辺りが辛いことがあります。(パフォーマンス問題もありますが今回はReduxを使う前提です)

今回はそれを解決すべく、Redux Toolkitの使い方をサンプルコードを交えて解説します。

バージョン
  • react 16.12.0
  • @reduxjs/toolkit 1.2.4

よくあるRedux

よくある構成として、containers/もしくはpages/の中にindex.js(tsx)をおき、reduxに関連するファイルをおいていました。

例えば、何らかのデータをAPIからfetchする場合は下記の流れで実装していました。

1 ActionTypeを定義

export const FETCH_DATA = 'FETCH_DATA';
export const FETCH_DATA_SUCCESS = 'FETCH_DATA_SUCCESS';
export const FETCH_DATA_ERROR = 'FETCH_DATA_ERROR';

2 Actionを定義

import {
  FETCH_DATA,
  FETCH_DATA_SUCCESS,
  FETCH_DATA_ERROR
} from './ActionType';

export const fetchData = () => {
  return {
    type: FETCH_DATA,
  };
};

export const fetchDataSuccess = (data) => {
  return {
    type: FETCH_DATA_SUCCESS,
    data,
  };
};

export const fetchDataError = () => {
  return {
    type: FETCH_DATA_ERROR,
  };
};

3 Reducerを定義

import {
  FETCH_DATA,
  FETCH_DATA_SUCCESS,
  FETCH_DATA_ERROR
} from './ActionType';

const initialState = {
  loading: false,
  data: [],
  error: ""
};

export default (state = initialState, action) => {
  switch (action.type) {
    case FETCH_DATA:
      return {
        ...state,
        loading: true
      };
    case FETCH_DATA_SUCCESS:
      return {
        ...state,
        data: action.data,
        loading: false
      };
    case FETCH_DATA_ERROR:
      return {
        ...state,
        loading: false
      };
    default:
      return state;
  }
};

4 Actionをdispatch

this.props.fetchData();

const mapDispatchToProps = (dispatch) =>
  bindActionCreators(
    { fetchData},
    dispatch
  );

問題点

このパターンでいくつかのプロジェクトを進める中で、下記のような問題点が上がっていました。

  1. 毎回定形文を書かなければいけないつらみ
  2. packageが多いつらみ
  3. 学習コストのつらみ

これらを解決できるのが、Redux Toolkitです。

ドキュメント

Github

Redux Toolkit

Redux Toolkitとは

2019年にバージョン1.0が出た新しめのライブラリで、Reduxの開発にも携わっているMark Eriksonさんが開発したもので、まさに上記の課題を解決するために開発されました。

2021年1月現在で、4,700くらいスターがついています。

先ほどの例を書き換えてみる

先ほどの例をRedux Toolkitを使って書き換えてみます。

(TypeScriptに変更しています)

type FetchDataLoaded = {
  data: DataModel;
};

type SampleState = {
  data: DataModel;
};

const initialState: SampleState = {
  data: null
};

const sample = createSlice({
  name: "sample",
  initialState,
  reducers: {
    fetchData(state) {},
    fetchDataSuccess(state, action: PayloadAction<FetchDataLoaded>) {
      const { data } = action.payload;
      state.data = data;
    },
    fetchDataError(state) {}
  }
});

export const {
  fetchData,
  fetchDataSuccess,
  fetchDataError
} = article.actions;
export default sample.reducer;

export const fetchData = (): AppThunk => async dispatch => { // Thunkをデフォルトで利用。Saga等を使うことも可能
  try {
    dispatch(fetchData());
    const res = API叩く(先ほどの例ではsagaを使っていました)
    dispatch(
      fetchDataSuccess({
        data: res.data
      })
    );
  } catch (err) {
    dispatch(fetchDataError());
    throw err;
  }
};

だいぶシンプルに記述できるようになりました。

シンプルに実装できるように、いくつかのヘルパー(createSliceなど)を提供してくれています。

シンプルに記述できるので、基本action/reducer/action typesを1つのファイルで管理しても問題ないです。

内部的にimmerを使ってたりしている点も記述を簡単にすることを助けています。

まとめ

Redux Toolkitを利用すると、Reduxの恩恵を受けつつ、以前までのつらさを回避できます。

気になる方は使ってみてください。