Redux Toolkit
Redux Toolkitとは(React環境での解説になります)
ざっくり言うと、「データの状態」と「データの処理方法」をまとめて管理、記述できるもの。
まずは、Store、Slice という概念があります。
■Store
Slice全体を管理しているでっかい倉庫(Amazon)

■Slice
各種データを管理している区域の様なもの

■まずは「データの状態」だけでReduxの中身を見てみる
Redux Toolkit の中身について、ほぼフォルダ構造としてイメージ出来るので理解しやすいと思います。
// テキストで書き出すと以下の様なイメージ
store // Slice全体を管理しているでっかい倉庫(Amazon)
├ book // Sliceの名前で、区分している(区域、フォルダの様なもの)
└ camera //
// これをもっと階層を掘り下げるとこんな感じでデータが管理されてます。
store
├ book
│ itemList: {
│ {id: 1, name: 'React入門'},
│ {id: 2, name: 'Redux Toolkit入門'},
│ }
└ camera
itemList: {
{id: 1, name: 'Nikon D850'},
{id: 2, name: 'Nikon D800'},
}
■sliceに書き起こしてみる
// Book.ts
import { createSlice } from "@reduxjs/toolkit";
// 初期値として入れたいデータ
// 本来はAPIで取得したDBのデータを格納するが、ここではダミーを作成して説明
const bookItems = {
{id: 1, name: 'React入門'},
{id: 2, name: 'Redux Toolkit入門'},
}
// stateの初期状態(このSliceで扱う全データの初期状態)
// stateとは、データ全体、オブジェクトで、stateを更新するにはreducerを使う。
const initialState = {
itemList: bookItems
};
// Sliceを生成する
const bookSlice = createSlice({
name: "book", // Sliceの名前
initialState, // データの初期状態(上記のinitialStateがここで適応される)
reducers: { // データの処理について記述
// 一旦省略
}
});
// Reducerをエクスポートする
export default bookSlice.reducer;
// Camera.ts
import { createSlice } from "@reduxjs/toolkit";
const cameraItems = {
{id: 1, name: 'Nikon D850'},
{id: 2, name: 'Nikon D800'},
}
const initialState = {
itemList: cameraItems
};
const cameraSlice = createSlice({
name: "camera",
initialState,
reducers: {
// 一旦省略
}
});
// Reducerをエクスポートする
export default cameraSlice.reducer;
■SliceをStoreに読み込む
import { combineReducers } from "redux";
import { configureStore } from "@reduxjs/toolkit";
// それぞれ slice.reducer を default export している前提
import bookReducer from "./book";
import cameraReducer from "./camera";
const reducer = combineReducers({
book: bookReducer,
camera: cameraReducer
});
const store = configureStore({ reducer });
export default store;
■結果
以下の様なイメージでStore(倉庫)の中のSlice(区域)にデータが入り、管理されます。
区域には、各ジャンル別にデータ(在庫)を置いているイメージです。
store
book:
itemList: {
{id: 1, name: 'React入門'},
{id: 2, name: 'Redux Toolkit入門'},
}
camera:
itemList: {
{id: 1, name: 'Nikon D850'},
{id: 2, name: 'Nikon D800'},
}

ここまでが「データの管理」までのざっくりとしたイメージです。
reducers
次に、処理の話です。
ここから少しだけ作業が増えますが、ゆっくり辿って確認していきましょう。
先に動きの結果だけ言うと
① reducersは、データ処理後の結果をstateに反映する
② stateが反映されるとstoreが更新される
③ sotreが更新されるとコンポーネントに反映される。
↓倉庫で例えると
① レジで清算を行う → 減った在庫をstateに反映する
② stateが更新される → 在庫データをstoreに反映する
③ storeが更新される → どのレジからsotreにアクセスしても在庫が反映されている状態を確認出来る
■処理イメージ

■処理
// Book.ts
import { createSlice } from "@reduxjs/toolkit";
const bookItems = {
{id: 1, name: 'React入門'},
{id: 2, name: 'Redux Toolkit入門'},
}
const initialState = {
itemList: bookItems
};
const bookSlice = createSlice({
name: "book",
initialState,
reducers: {
updateItemList: (state, action) => {
// state.itemListは、initialStateの中のitemListの事をさしています。
// action.payloadは、state.itemListの中身に対して更新したい内容です。
state.itemList = action.payload
}
}
});
export default bookSlice.reducer;
上記のコメントにもあるように「updateItemList」でstate(データ/オブジェクト)に更新をかけています。
そして、reduxの処理はこれで完了です。
では、在庫が増えた、減ったの処理はどうするのか?
それは、レジ = コンポーネント側で処理します。(本来は、処理専用の関数ファイルを用意しますが、ここではコンポーネントにまとめて説明します)
そして、その処理は普通のJavaScriptです。
■コンポーネント側で関数作って処理
では早速処理と言いたい所ですが、処理をする前に、在庫が分からないと処理ができません。
ですので、レジ = コンポーネントに、sotreを経由して在庫を読み込み、処理してみましょう。
// useSelectorは、Sliceの中身を読み込むためのもの
// useDispatchは、Sliceのreducrsに処理の実行を依頼するために必要なもの
import { useSelector, useDispatch } from "react-redux";
// Book.tsのreducersを読み込む
import { updateItemList } from "../store/slice/Book";
const Component = () => {
// dispatchとして定数に設定
const dispatch = useDispatch();
// useSelectorを使ってsliceで管理しているデータを読み込む
const imteList = useSelector((state: RootState) => state.Book)
const deleteItem = () => {
// JavaScriptのpop()を使って配列の最後を削除
itemList.pop()
// dispatchを使って更新を×
dispatch(updateItemList(itemList))
}
return (
<button onClick={deleteItem}>click</button>
);
}
ここまで来ると、あとは普通にJavaScriptで処理しているだけです。
一応、流れを書き出すと
「const imteList = useSelector((state: RootState) => state.Book)」で、BookSliceで設定したitemLsitのデータが読み込まれます。
ここの解説で表すといかのデータです。
BookSlice
itemList:
{
{id: 1, name: 'React入門'},
{id: 2, name: 'Redux Toolkit入門'},
}
そして「Component」のボタンを押すと「deleteItem」が実行されます。
「deleteItem」は、配列の最後を削除するという事なので、1回押せば次のように配列が変わります。
{
{id: 1, name: 'React入門'},
}
で「dispatch(updateItemList(itemList))」でSliceのreducersの「updateItemList」が実行されます。
updateItemList: (state, action) => {
state.itemList = action.payload
}
action.payload には、deleteItemで処理された「{id: 1, name: 'React入門’}」が渡されます。
そして、state.itemList = action.payload としてるので、
itemListの中身は「{id: 1, name: 'React入門’}」に書き換わります。
ここれで、データの更新が完了されました!
しかし、ここまでではありません。最後にSliceが更新されると
Storeに反映されBookSliceを読み込んでいるコンポーネントに
再レンダリングがかかり、コンポーネントも再描画されます。
ここまでが一連の流れです。
ここでは、ざっくり概要を掴みたい人に色々省略して書いたものです。
より詳しく知りたい方は、以下が参考になります。
ディスカッション
コメント一覧
まだ、コメントがありません