Javascript 更新 redux 存储中的嵌套数据
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32135779/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Updating nested data in redux store
提问by Clarkie
What's the best/correct way to update a nested array of data in a store using redux?
使用 redux 更新存储中嵌套数据数组的最佳/正确方法是什么?
My store looks like this:
我的商店看起来像这样:
{
items:{
1: {
id: 1,
key: "value",
links: [
{
id: 10001
data: "some more stuff"
},
...
]
},
...
}
}
I have a pair of asynchronous actions that updates the complete items
object but I have another pair of actions that I want to update a specific links
array.
我有一对更新完整items
对象的异步操作,但我有另一对要更新特定links
数组的操作。
My reducer currently looks like this but I'm not sure if this is the correct approach:
我的减速器目前看起来像这样,但我不确定这是否是正确的方法:
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,
});
}
回答by Dan Abramov
Jonny's answeris correct (never mutate the state given to you!) but I wanted to add another point to it. If all your objects have IDs, it's generally a bad idea to keep the state shape nested.
Jonny 的回答是正确的(永远不要改变给你的状态!)但我想补充一点。如果您的所有对象都有 ID,那么保持状态形状嵌套通常是个坏主意。
This:
这个:
{
items: {
1: {
id: 1,
links: [{
id: 10001
}]
}
}
}
is a shape that is hard to update.
是一种难以更新的形状。
It doesn't have to be this way! You can instead store it like this:
不必这样!你可以像这样存储它:
{
items: {
1: {
id: 1,
links: [10001]
}
},
links: {
10001: {
id: 10001
}
}
}
This is much easier for update because there is just one canonical copy of any entity. If you need to let user “edit a link”, there is just one place where it needs to be updated—and it's completely independent of items
or anything other referring to links
.
这更容易更新,因为任何实体都只有一个规范副本。如果您需要让用户“编辑链接”,则只有一个地方需要更新——而且它完全独立items
于links
.
To get your API responses into such a shape, you can use normalizr. Once your entities inside the server actions are normalized, you can write a simple reducer that merges them into the current state:
要将您的 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;
}
Please see Redux real-world
example for a demo of such approach.
real-world
有关此类方法的演示,请参阅 Redux示例。
回答by Jonny Buchanan
React's update()
immutability helperis a convenient way to create an updated version of a plain old JavaScript object without mutating it.
React 的update()
immutability helper是一种方便的方式来创建一个普通旧 JavaScript 对象的更新版本,而不需要改变它。
You give it the source object to be updated and an object describing paths to the pieces which need to be updated and changes that need to be made.
你给它一个要更新的源对象和一个描述需要更新的部分和需要进行的更改的路径的对象。
e.g., if an action had id
and link
properties and you wanted to push the link
to an array of links in an item keyed with the id
:
例如,如果一个操作具有id
和link
属性,并且您想将 推link
送到以 为键的项目中的链接数组id
:
var update = require('react/lib/update')
// ...
return update(state, {
items: {
[action.id]: {
links: {$push: action.link}
}
}
})
(Example uses an ES6 computed property name for action.id
)
(示例使用 ES6 计算属性名称action.id
)