使用redux更新商店中嵌套数据的最佳/正确方法是什么?
我的商店看起来像这样:
{
items:{
1: {
id: 1,
key: "value",
links: [
{
id: 10001
data: "some more stuff"
},
...
]
},
...
}
}
我有一对异步操作可以更新完整的items
对象,但我还有另外一对要更新特定links
数组的操作。
我的减速机目前看起来像这样,但我不确定这是否是正确的方法:
switch (action.type) {
case RESOURCE_TYPE_LINK_ADD_SUCCESS:
// TODO: check whether the following is acceptable or should we create a new one?
state.items[action.resourceTypeId].isSourceOf.push(action.resourceTypeLink);
return Object.assign({}, state, {
items: state.items,
});
}
答案 0 :(得分:58)
Jonny's answer是正确的(永远不会改变给你的状态!)但是我想补充一点。如果所有对象都有ID,那么保持状态形状嵌套通常是个坏主意。
此:
{
items: {
1: {
id: 1,
links: [{
id: 10001
}]
}
}
}
是一种难以更新的形状。
不一定是这样!你可以这样存储它:
{
items: {
1: {
id: 1,
links: [10001]
}
},
links: {
10001: {
id: 10001
}
}
}
这更容易更新,因为只有一个任何实体的规范副本。如果您需要让用户“编辑链接”,则只需要更新一个位置 - 它完全独立于items
或其他任何引用links
的内容。
要将API响应转换为此类形状,您可以使用normalizr。一旦您的服务器操作中的实体被规范化,您就可以编写一个简单的reducer,将它们合并到当前状态:
import merge from 'lodash/object/merge';
function entities(state = { items: {}, links: {} }, action) {
if (action.response && action.response.entities) {
return merge({}, state, action.response.entities);
}
return state;
}
请参阅Redux real-world
示例,了解此类方法的演示。
答案 1 :(得分:50)
React的update()
immutability helper是一种创建普通旧JavaScript对象的更新版本而不会改变它的便捷方式。
您可以为其提供要更新的源对象,以及描述需要更新的部分的路径的对象以及需要进行的更改。
例如,如果某个操作具有id
和link
属性,并且您希望将link
推送到以id
键入的项目中的一系列链接:< / p>
var update = require('react/lib/update')
// ...
return update(state, {
items: {
[action.id]: {
links: {$push: action.link}
}
}
})
(示例使用action.id
的ES6计算属性名称)