序章

レデューサーでReduxの状態を初期状態にリセットする必要があったことはありますか? 状態をリセットすることは、多くのアプリが行う必要があることです。 アプリの状態をリセットする必要がある典型的な例は、ユーザーがログアウトするときです。

この記事では、状態のリセットの集中化、レデューサーごとのリセットロジック、およびレデューサーのリセットからの除外について学習します。

前提条件

このチュートリアルに従うには、次のものが必要です。

  • ReactとReduxにある程度精通している。 Reduxを使い始めた場合は、この投稿を参照できます。

このチュートリアルは、reduxv4.1.0で検証されました。

RESET_APPの制限を理解する

最も単純なアプローチは、すべてのレデューサーにRESET_APP条件を追加することです。

次の形状のusersレデューサーについて考えてみます。

const usersDefaultState = [];

const users = (state = usersDefaultState, { type, payload }) => {
  switch (type) {
    case 'ADD_USER':
      return [...state, payload];
    default:
      return state;
  }
};

次に、usersDefaultStateを返すために、スイッチにRESET_APPケースを追加します。

const usersDefaultState = [];

const users = (state = usersDefaultState, { type, payload }) => {
  switch (type) {
    case 'RESET_APP':
      return usersDefaultState;
    case 'ADD_USER':
      return [...state, payload];
    default:
      return state;
  }
};

これは1つまたは2つのレデューサーでは許容されますが、実際のアプリでは、レデューサーごとに同じコードを繰り返すことになり、多くの場合、次のようになります。

const usersDefaultState = [];

const users = (state = usersDefaultState, { type, payload }) => {
  switch (type) {
    case 'RESET_APP':
      return usersDefaultState;
    case 'ADD_USER':
      return [...state, payload];
    default:
      return state;
  }
};

const articlesDefaultState = [];

const articles = (state = articlesDefaultState, { type, payload }) => {
  switch (type) {
    case 'RESET_APP':
      return articlesDefaultState;
    case 'ADD_ARTICLE':
      return [...state, payload];
    default:
      return state;
  }
};

DRY (繰り返しないでください)を覚えていますか? まあ、このコードは実際にはその原則に準拠しておらず、それは開発者として私たちが避けなければならないことです。

国家のリセットを一元化する

アプリを1か所でリセットするためのロジックを再利用する秘訣は、アプリのルートレデューサーの上にルートレデューサーを作成することです。 これは、レデューサーの上にあるレデューサーであり、その状態を確認し、必要に応じて適用します。

通常、combineReducers関数を使用して、reduxストア用の単一のルートレデューサーを作成します。

import { combineReducers } from 'redux';

const usersDefaultState = [];

const users = (state = usersDefaultState, { type, payload }) => //...

const articlesDefaultState = [];

const articles = (state = articlesDefaultState, { type, payload }) => //...

const allReducers = combineReducers({
  users,
  articles
});

この場合、allReducersは、ReduxのcreateStore関数に渡すアプリのルートレデューサーです。

その上にラッピングルートレデューサーを作成するには、そのルートレデューサーを呼び出す関数を定義する必要があります。

const rootReducer = (state, action) => {
  return allReducers(state, action);
}

現在、rootReducerは、allReducers呼び出しの間にある関数として機能しています。 その呼び出しの直前に、レデューサー呼び出しの前に適用される共通の機能を追加できます。 そして、アプリをリセットするために、undefinedに設定された状態を渡すことができます。

const rootReducer = (state, action) => {
  if (action.type === 'RESET_APP') {
    state = undefined;
  }

  return allReducers(state, action);
}

待って、何? なぜそれがアプリをリセットするのでしょうか? さて、レデューサーの定義を分析すると、次のようになります。

const users = (state = usersDefaultState, { type, payload }) => //...

この場合、stateパラメーターのデフォルト値はusersDefaultStateであり、関数のデフォルトパラメーターは、受信したパラメーター値が[X192Xの場合にのみ適用されます。 ](nullではなく、undefinedのみ)。 そのため、すべてのレデューサーが受け取る状態がデフォルトの状態です。

待って、状態を変えてみませんか? いいえ、状態参照をundefinedに変更しますが、変更しません。 状態の変更はReduxの原則に反することを忘れないでください。

レデューサーごとのリセットロジックの使用

rootReducerを使用して集中リセットロジックを適用しても、他のレデューサーでRESET_APPアクションのカスタム機能を使用できなくなることはありません。

たとえば、articlesレデューサーは、RESET_APPがトリガーされたときに、デフォルト以外の状態を返す必要があるとします。

const articles = (state = articlesDefaultState, { type, payload }) => {
  switch (type) {
    case "RESET_APP":
      return "App is reset";
    case "ADD_ARTICLE":
      return [...state, payload];
    default:
      return state;
  }
};

重要なのは、デフォルトでは、すべてのレデューサーがデフォルトの状態を返すようにし、必要な場合にのみカスタムリセット動作を行うことです。

レデューサーをリセットから除外する

一部の特定のレデューサーがリセットされるのを避けたい場合があります。 除外したい状態のスライスを保持することで、それを防ぐことができます。

たとえば、articlesレデューサーをリセットから除外する場合:

const rootReducer = (state, action) => {
  if (action.type === 'RESET_APP') {
    const { articles } = state;
    state = { articles };
  }

  return allReducers(state, action);
};

ここで何が起こっているのですか? combineReducers関数は、レデューサーを組み合わせて対応する状態を渡すため、各レデューサーはスコープ内の状態の一部のみを持ちます。

この場合、state = { articles }で状態のarticles部分を選択すると、関数allReducersstate.articlesarticlesレデューサーに渡します。 state.usersからusersレデューサー。 state.usersundefinedであり、state.articlesはそうではないため、ユーザーレデューサーのみがリセットされます。

結論

この記事では、状態のリセットの集中化、レデューサーごとのリセットロジック、およびレデューサーのリセットからの除外について学習しました。

通常、コードの重複を回避する方法は複数ありますが、実際にDRYの原則に従うと、コードがより理解しやすく、保守しやすくなります。