【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