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
);
問題点
このパターンでいくつかのプロジェクトを進める中で、下記のような問題点が上がっていました。
- 毎回定形文を書かなければいけないつらみ
- packageが多いつらみ
- 学習コストのつらみ
これらを解決できるのが、Redux Toolkitです。
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の恩恵を受けつつ、以前までのつらさ
を回避できます。
気になる方は使ってみてください。