Yanonoblog!

こつこつと

Redux DevToolsの概要と活用法

はじめに

Reduxの公式ドキュメントに沿って概要を押さえつつ、気になった部分を深掘って整理しています。

本記事では 、Reduxのサンプルアプリを通してDevToolsの概要についてまとめていきます。

Reduxのサンプルアプリを起動

下記のコマンドで公式リファレンス通りのReduxアプリを自動で構築します。

npx create-react-app redux-essentials-example --template redux

セットアップされているコマンドを実行するとローカル環境の動作を確認することができます。

npm start

Reactアプリが起動できました。

カウンターアプリがデフォルトで組み込まれています。

ソース

下記はスライスを定義するソースです。

要約するとカウンター値の増加と減少処理、任意の量でカウンター値の増加処理、非同期でのカウント処理、条件付きのカウンター増加処理などが実装されています。

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import { fetchCount } from './counterAPI';

const initialState = {
  value: 0,
  status: 'idle',
};

// 下記の関数は「thunk」と呼ばれ、非同期のロジックを処理するために使用します。
// 普通のアクションと同様にdispatchできます:`dispatch(incrementAsync(10))`。
// これは`dispatch`関数を最初の引数としてthunkを呼び出します。その後、非同期のコードが実行され、他のアクションがdispatchされます。
// Thunkは通常、非同期リクエストを行うために使用されます。
export const incrementAsync = createAsyncThunk(
  'counter/fetchCount',
  async (amount) => {
    const response = await fetchCount(amount);
    // 返り値は `fulfilled` アクションの payload となります
    return response.data;
  }
);

export const counterSlice = createSlice({
  name: 'counter',
  initialState,
  // `reducers`フィールドでは、reducerを定義し、関連するアクションを生成します
  reducers: {
    increment: (state) => {
      // Redux Toolkitでは、reducer内で"mutating"なロジックを書くことが許されています。
      // しかし、実際にはstateを変更していません。なぜなら、Immerライブラリを使用しており、
      // "ドラフトstate"に対する変更を検出し、それに基づいた新しいイミュータブルなstateを生成するからです
      state.value += 1;
    },
    decrement: (state) => {
      state.value -= 1;
    },
    // `PayloadAction`型を使って `action.payload` の内容を宣言します
    incrementByAmount: (state, action) => {
      state.value += action.payload;
    },
  },
  // `extraReducers`フィールドでは、他の場所で定義されたアクションを処理できます
  // createAsyncThunkによって生成されたアクションや、他のスライス内のアクションを含みます
  extraReducers: (builder) => {
    builder
      .addCase(incrementAsync.pending, (state) => {
        state.status = 'loading';
      })
      .addCase(incrementAsync.fulfilled, (state, action) => {
        state.status = 'idle';
        state.value += action.payload;
      });
  },
});

export const { increment, decrement, incrementByAmount } = counterSlice.actions;

// 下記の関数は「selector」と呼ばれ、stateから値を選択することができます
// Selectorは、スライスファイル内だけでなく、使用される場所でインラインで定義することもできます。
// 例えば:`useSelector((state: RootState) => state.counter.value)`
export const selectCount = (state) => state.counter.value;

// また、手動でthunkを書くこともできます。これには同期的なロジックと非同期的なロジックの両方が含まれる場合があります。
// 現在のstateに基づいてアクションを条件付きでdispatchする例を以下に示します。
export const incrementIfOdd = (amount) => (dispatch, getState) => {
  const currentValue = selectCount(getState());
  if (currentValue % 2 === 1) {
    dispatch(incrementByAmount(amount));
  }
};

export default counterSlice.reducer;

Devtools

ブラウザのDevToolsで[Redux]タブを開くとストアの状態を見ることができます。

DevTools は、アプリの使用中にストアの状態がどのように変化するかを示します。

アプリ内で何が起こっているのか、時間の経過とともに状態がどのように変化するのかを確認できます。

Storeリスト

Storeのリストを見ることができます。

アクションがdispatchされると、アクションの内容がリストにも反映されます。

Actionタブ

Storeリストに反映されたアクションのtypeとpayloadが反映される場所です。

Diffタブ

各アクションによって発生したStateの差分が反映される場所です。

Trace

アクションが発火された時点でのコードのスナップショットを確認することができます。

スタックトレース(エラーが発生したときにどの関数がどの順序で呼ばれたかを表示するもの)を表示する機能もあるため、問題の原因を特定しやすくなります。

参考

続く…

コメント

本記事の内容は以上になります!

書籍の続きのアウトプットも随時更新したいと思います。


プログラミングスクールのご紹介 (卒業生より)

お世話になったプログラミングスクールであるRUNTEQです♪

https://runteq.jp/r/ohtFwbjW

こちらのリンクを経由すると1万円引きになります。

RUNTEQを通じて開発学習の末、受託開発企業をご紹介いただき、現在も双方とご縁があります。

もし、興味がありましたらお気軽にコメントか、TwitterのDMでお声掛けください。

https://twitter.com/outputky