これは有効なreduxレデューサーですか?
function reducer(state={ byId: {}, ids: [] }, action) {
switch (action.type) {
case 'ADD':
state = { ...state }
state.byId[action.id] = action.value
state.ids.push(action.id)
return state
default:
return state
}
}
状態全体が最初にシャロークローンされるため、新しいオブジェクトが返されますが、内部オブジェクトは同じままで変更されます。
または、次のようなことをする必要がありますか?
function reducer(state={ byId: {}, ids: [] }, action) {
switch (action.type) {
case 'ADD':
return {
...state,
byId: {
...state.byId,
[action.id]: action.value
},
ids: [ ...state.ids, action.id ]
}
default:
return state
}
}
最初のアプローチで見られる副作用は、DevToolsLogMonitorにあります。
byId
)を展開すると、以前は別の状態であった場合でも、最新のノードと同じ値が表示されますLogMonitorの単なるバグですか、それとも2番目のアプローチが正しいですか? ミューテーションの前にstate = _.cloneDeep(state)
を追加すると、実際には正常に機能し、LogMonitorが同じオブジェクト、つまり同じ値を再利用することを証明します。
アプリの残りの部分は正常に動作しますが、 @connect
edビューは正しく更新されます。
いいえ、その最初の例は状態を完全に変化させることです。 最初の浅いコピーは新しいオブジェクトを作成しますが、新しいオブジェクトは元のオブジェクトと同じbyId
およびids
参照を指します。 したがって、 byId[action.id] = action.value
とids.push(action.id)
を実行すると、元のアイテムが変更されます。
後者の例はあなたがする必要があることです。 明らかに、あなたが物事を入れ子にしているなら、それは幾分冗長になる可能性があります。 あなたのためにそれを抽象化しようとするいくつかのユーティリティライブラリがあります、そして私はそれらのいくつかを私のReduxライブラリリストの不変データページにリストしています。
Redux FAQには、状態を不変に正しく更新することをカバーする質問もあります: http: //redux.js.org/docs/FAQ.html#react-not-rerendering。
後者の例はあなたがする必要があることです。 明らかに、あなたが物事を入れ子にしているなら、それは幾分冗長になる可能性があります。 あなたのためにそれを抽象化しようとするいくつかのユーティリティライブラリがあります、そして私はそれらのいくつかを私のReduxライブラリリストの不変データページにリストしています。
また、レデューサー構成はこれに役立ちます。
function byId(state = {}, action) {
switch (action.type) {
case 'ADD':
return {
...state,
[action.id]: action.value
}
default:
return state
}
}
function ids(state = [], action) {
switch (action.type) {
case 'ADD':
return [ ...state, action.id ]
default:
return state
}
}
const reducer = combineReducers({
byId,
ids
})
@ gaearon @ markeriksonありがとう。 動的なインデックス付きリストを(IDで)管理する高次リデューサーを作成することになりました。
コード: https ://gist.github.com/elado/95484b754f31fcd6846c7e75de4aafe4
最も参考になるコメント
また、レデューサー構成はこれに役立ちます。