【React】Redux toolkitの使い方(Slice作成、Redux Dev Toolsでstateを確認)

React

ReactでReduxを使う方法を紹介します。

ReactでReduxを使う方法

公式の手順は以下にあります。
https://react-redux.js.org/introduction/getting-started

実際はReactを作成してからReduxをいれることが多いと思うので、そのやり方を紹介します。

Reactのプロジェクトを作成

プロジェクトのファイルを作成します。


npx create-react-app [アプリ名]
npx create-react-app redux-app

ファイルのインストールが完了したら、cdでアプリ名のフォルダに移動します。


cd redux-app

そして、VS Codeなら以下コマンドで開けます。


code .

そして、以下コマンドで開発を始められます。


npm start

Reduxを既存のプロジェクトにいれる

以下コマンドで既存ReactプロジェクトにReduxをインストールできます。


npm install react-redux @reduxjs/toolkit

Reduxのプラグインを導入する

Chromeであれば、Redux DevToolsがあります。

そして、redux dev tools extensionで検索すると以下の拡張機能をgithubで配布している方がいるので、
それをいれます。
https://github.com/reduxjs/redux-devtools

最新は上記のURLになります。
また、拡張をする方法は、以下のページにかかれています。
https://github.com/reduxjs/redux-devtools/tree/main/extension#installation

やり方は簡単で、

<code class="language-javascript">const store = createStore(
   reducer, /* preloadedState, */
+  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
 );

上記のように+部分を追加するだけでOKです。

src/store.jsを作成

srcフォルダ直下にstore.jsを作成してstoreを作成します。

import { configureStore } from "@reduxjs/toolkit";

// storeにreducerをいれていく
export const store = configureStore({
  reducer: {},
});

reduxのtoolkitをインストールすると、configureStoreを使えます。
storeはreducerを保持していくので、上のような形で記述していきます。

index.jsでstoreをアプリ全体で使えるようにする

import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import App from "./App";
import { store } from "./store"; //作成したstoreを追加
import { Provider } from "react-redux"; //Providerで全体でstoreを使えるようにする

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);

作成したstoreとreact-reduxにあるProviderをインポートします。
そして、ProviderでAppをラップして、storeをpropsとして渡すことで、
アプリ全体で使えるようになります。

Sliceを作成

Sliceとはそもそも何?

Sliceとは、Storeというを輪切りにしたようなイメージです。
Storeはstate、Reducer、ActionCreatorを保持しています。
この3つ(state、Reducer、ActionCreator)の組み合わせをSliceといいます。
StoreはこのSliceをたくさん保持することができます。

src/features/cart/CartSlice.jsを作成

src以下は好きに名前をつければいいのですが、
今回は買い物かごのアプリを例にします。
src/features/cart/CartSlice.jsを作成して、以下を記述します。

import { createSlice } from "@reduxjs/toolkit";

// 買い物かごの初期化
const initialState = {
  cartItems: [], // ひとつひとつの商品
  amount: 0, // カートに入れた合計商品数量
  total: 0, // 合計金額
}
const cartSlice = createSlice({
  name: "cart", // sliceの名前、useSelectorでアクセスするときに使う
  initialState, // 初期の状態
  reducers: {}, // reducerを格納、actionCreatorはreducerを作成すると自動的に作られる
});

スライスは、@reduxjs/toolkit"のcreateSliceを使うことで作成できます。
オブジェクトの中に含むことは、スライスの名前、初期状態、reducersです。
スライスの名前は、useSelectorでアクセスするときに使います。
reducersでは、複数のreducerを格納することができます。
スライスには、actionCreatorも必要ですが、@reduxjs/toolkitを使えば、reducerを作成するとactionCreatorは自動的に作られます。

Redux Dev Toolsで確認できるようにする

src/features/cart/CartSlice.jsの最後に、以下を追加します。

export default cartSlice.reducer; // reducerをexport

createSliceで作成したスライスにはreducerというメソッドがあるので、それだけをエクスポートします。

そして、src/store.jsを以下のように書き換えます。

import { configureStore } from "@reduxjs/toolkit";
import cartReducer from "./features/cart/CartSlice";  // reducerをimport

export const store = configureStore({
  reducer: {
    cart: cartReducer, // reducerを追加
  },
});

こうすることで、reducerのプロパティに格納した名前、上のケースではcartという名前で状態を確認することができます。

useSelectorでstoreにアクセスする

useSelectorでstoreにアクセスすることができます。
任意のコンポーネントで以下のようにインポートします。

import { useSelector } from "react-redux";

そして、以下のようにしてコンポーネント内で使用します。

const Component = () => {
  // const amount = useSelector((store) => store.cart.amount);
  const { amount } = useSelector((store) => store.cart);
  console.log(amount);
  return (
	<div>{amount}</div>
  );
};

上の例では、src/store.jsのreducerで設定した「cart」という変数にアクセスしています。
一般的には分割代入を使って必要な値のみを取り出します。

actionCreator

import { createSlice } from "@reduxjs/toolkit";

// 買い物かごの初期化
const initialState = {
  cartItems: [], // ひとつひとつの商品
  amount: 0, // カートに入れた合計商品数量
  total: 0, // 合計金額
};
const cartSlice = createSlice({
  name: "cart", // sliceの名前、useSelectorでアクセスするときに使う
  initialState, // 初期の状態
  reducers: {
    // プロパティ名がactionCreatorとして作られる
    clearCart: (state) => {
      // 空にする
      return { cartItems: [], amount: 0, total: 0 };
    },
  }, // reducerを格納、actionCreatorはreducerを作成すると自動的に作られる
});

// console.log(cartSlice); //actions.clearCartがある
export const { clearCart } = cartSlice.actions;
export default cartSlice.reducer; // reducerをexport

reducersの中にプロパティをセットして、関数で処理内容を記述します。
すると、自動的にプロパティ名でactionCreatorが作成されます。
コンソールで出力すると、actions.clearCartがあるのがわかります。
なので、それをエクスポートして利用します。

useDispatchで通知する

使いたいコンポーネントでまずは、インポートします。

import { useDispatch } from "react-redux";

そして、変数を作成します。

const dispatch = useDispatch();

そして、JSXでたとえばonClickで使います。

        <button onClick={() => dispatch(clearCart())}>
          全削除
        </button>

そうすると、クリックイベントを機に通知されます。

ちなみにdispatchするときに引数に値を渡すとpayloadにセットされます。

  reducers: {
    removeItem: (state, action) => {
      console.log(action);
    }
  },

上のようにたとえば、reducerにremoveItemという名前のプロパティを登録して、
ループしているコンポーネントの中で、以下のように使用します。
onClick={() => dispatch(removeItem(id))}
すると、actionの中にtypeとpayloadがあり、そのpayloadに各idが含まれます。titleならtitleがpayloadに入ります。

React

Posted by devsakaso