序章
レデューサーで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部分を選択すると、関数allReducersはstate.articlesをarticlesレデューサーに渡します。 state.usersからusersレデューサー。 state.usersはundefinedであり、state.articlesはそうではないため、ユーザーレデューサーのみがリセットされます。
結論
この記事では、状態のリセットの集中化、レデューサーごとのリセットロジック、およびレデューサーのリセットからの除外について学習しました。
通常、コードの重複を回避する方法は複数ありますが、実際にDRYの原則に従うと、コードがより理解しやすく、保守しやすくなります。