Reduxアプリの初期状態は、次の2つの方法で設定できます。
初期状態をストアに渡す場合、ストアからその状態をどのように読み取り、それをレデューサーの最初の引数にしますか?
回答:
TL; DR
なければ
combineReducers()
または類似マニュアルコード、initialState
いつも以上の勝利state = ...
ので減速にstate
減速に渡されているinitialState
といないundefined
ES6引数の構文は、この場合には適用されませんので、。
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
に呼ばれた42
2番目の引数として。この引数は、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
減速。とレデューサーの両方が引数として受け取り、デフォルト値を指定すると、それらが返されます。a
b
undefined
state
state
これは、結合されたレデューサーが{ 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
引数として呼び出されたときにレデューサーから初期状態を返す場合(これを実装する最も簡単な方法は、state
ES6のデフォルトの引数値を指定することです)、次のようになります。組み合わせたレデューサーにとって便利な動作です。関数に渡すオブジェクトの対応する値を優先しますが、何も渡さなかった場合、または対応するフィールドが設定されていない場合は、代わりにレデューサーによって指定されたデフォルトの引数が選択されます。initialState
createStore()
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
。どうもありがとうございました。