Reduxアプリの初期状態は、次の2つの方法で設定できます。
初期状態をストアに渡す場合、ストアからその状態をどのように読み取り、それをレデューサーの最初の引数にしますか?
回答:
TL; DR
なければ
combineReducers()または類似マニュアルコード、initialStateいつも以上の勝利state = ...ので減速にstate減速に渡されているinitialStateといないundefinedES6引数の構文は、この場合には適用されませんので、。
combineReducers()行動より微妙です。で状態が指定されているレデューサーは、それinitialStateを受け取りstateます。他のレデューサーは受信undefinedし、そのため、state = ...指定したデフォルトの引数にフォールバックします。一般に、
initialStateレデューサーによって指定された状態に勝ちます。これは、レデューサーは理にかなっている初期データを指定することができます彼らにデフォルト引数として、だけでなく、あなたには、いくつかの永続ストレージやサーバーからのストアを水和しているときに(完全または部分的に)ロード既存のデータを可能にします。
まず、レデューサーが1つしかない場合を考えてみましょう。
使用しないとしましょうcombineReducers()。
次に、レデューサーは次のようになります。
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT': return state + 1;
case 'DECREMENT': return state - 1;
default: return state;
}
}
それを使ってストアを作成するとします。
import { createStore } from 'redux';
let store = createStore(counter);
console.log(store.getState()); // 0
初期状態はゼロです。どうして?の2番目の引数はcreateStoreでしたundefined。これは、state初めてレデューサーに渡されます。Reduxが初期化されると、状態を埋めるために「ダミー」アクションがディスパッチされます。したがって、counterレデューサーはにstate等しいで呼び出されましたundefined。これは、デフォルトの引数を「アクティブ化」する場合とまったく同じです。したがって、stateは0デフォルトstate値(state = 0)のとおりになりました。この状態(0)が返されます。
別のシナリオを考えてみましょう。
import { createStore } from 'redux';
let store = createStore(counter, 42);
console.log(store.getState()); // 42
今回はなぜであり42、そうではないの0ですか?そのためcreateStoreに呼ばれた422番目の引数として。この引数は、stateダミーアクションとともにレデューサーに渡されます。今回stateは未定義ではないので(42!)、ES6のデフォルトの引数構文は効果がありません。stateで42、かつ42減速から返されます。
次に、を使用する場合を考えてみましょうcombineReducers()。
2つのレデューサーがあります。
function a(state = 'lol', action) {
return state;
}
function b(state = 'wat', action) {
return state;
}
によって生成されるレデューサーはcombineReducers({ a, b })次のようになります。
// const combined = combineReducers({ a, b })
function combined(state = {}, action) {
return {
a: a(state.a, action),
b: b(state.b, action)
};
}
を指定createStoreせずに呼び出すと、initialStateをに初期化さstateれ{}ます。したがって、state.aとstate.bなりundefined、それが呼び出した時点でaとb減速。とレデューサーの両方が引数として受け取り、デフォルト値を指定すると、それらが返されます。abundefined statestateこれは、結合されたレデューサーが{ a: 'lol', b: 'wat' }最初の呼び出しで状態オブジェクトを返す方法です。
import { createStore } from 'redux';
let store = createStore(combined);
console.log(store.getState()); // { a: 'lol', b: 'wat' }
別のシナリオを考えてみましょう。
import { createStore } from 'redux';
let store = createStore(combined, { a: 'horse' });
console.log(store.getState()); // { a: 'horse', b: 'wat' }
ここでinitialState、の引数としてを指定しましたcreateStore()。結合されたレデューサーから返される状態は、レデューサーに指定した初期状態と、レデューサーがそれ自体を選択したことを指定したデフォルトの引数を組み合わせaたもの'wat'ですb。
結合されたレデューサーが何をするかを思い出してみましょう:
// const combined = combineReducers({ a, b })
function combined(state = {}, action) {
return {
a: a(state.a, action),
b: b(state.b, action)
};
}
この場合、stateが指定されたため、にフォールバックしませんでした{}。これは、aフィールドがに等しいオブジェクトでした'horse'が、bフィールドはありませんでした。これが、aレデューサーが'horse'そのとして受け取ってstate喜んで返したのに、bレデューサーがundefinedそのとして受け取ったstateためにデフォルトのアイデアを返した理由ですstate(この例では'wat')。これが私たちの{ a: 'horse', b: 'wat' }見返りです。
これを要約すると、Reduxの規則に従いundefined、state引数として呼び出されたときにレデューサーから初期状態を返す場合(これを実装する最も簡単な方法は、stateES6のデフォルトの引数値を指定することです)、次のようになります。組み合わせたレデューサーにとって便利な動作です。関数に渡すオブジェクトの対応する値を優先しますが、何も渡さなかった場合、または対応するフィールドが設定されていない場合は、代わりにレデューサーによって指定されたデフォルトの引数が選択されます。initialStatecreateStore()stateこのアプローチは、既存のデータの初期化とハイドレーションの両方を提供するためうまく機能しますが、データが保存されていない場合、個々のレデューサーは状態をリセットできます。もちろんcombineReducers()、多くのレベルで使用できるため、このパターンを再帰的に適用することも、レデューサーを呼び出して状態ツリーの関連部分を与えることでレデューサーを手動で作成することもできます。
function counter(state = 0, action)つまり、またはなど、レデューサーを定義する場所で初期状態を選択することを意味しますfunction visibleIds(state = [], action)。
一言で言えば、初期状態をレデューサーに渡すのはReduxであり、何もする必要はありません。
電話をかけるcreateStore(reducer, [initialState])と、最初のアクションが入ったときにレデューサーに渡される初期状態が何であるかをReduxに知らせています。
あなたが言及する2番目のオプションは、ストアの作成時に初期状態を渡さなかった場合にのみ適用されます。すなわち
function todoApp(state = initialState, action)
状態は、Reduxによって渡された状態がなかった場合にのみ初期化されます
menuState、メニューリデューサーにstate.menuストアからの値を読み取り、それを初期状態として使用するように指示するにはどうすればよいですか?
これがあなたの要求に答えることを願っています(initialStateを渡してその状態を返す間にレデューサーを初期化することとして理解しました)
これが私たちのやり方です(警告:Typescriptコードからコピーされました)。
その要点はif(!state)、mainReducer(factory)関数でのテストです。
function getInitialState(): MainState {
return {
prop1: 'value1',
prop1: 'value2',
...
}
}
const reducer = combineReducers(
{
main: mainReducer( getInitialState() ),
...
}
)
const mainReducer = ( initialState: MainState ): Reducer => {
return ( state: MainState, action: Action ): MainState => {
if ( !state ) {
return initialState
}
console.log( 'Main reducer action: ', action )
switch ( action.type ) {
....
}
}
}
combineReducers。どうもありがとうございました。