React.js: setState覆盖,而不是合并
React.js: setState overwriting, not merging
我是React.JS的新手,我正在尝试构建一个砖石风格的布局。
我将每个元素呈现给DOM,然后我需要循环遍历每个项目,并根据前面的元素应用x和y位置。
初始模型是这样的:
[
{
"title": "The Forrest",
"description": "some cool text",
"imgSmallSrc": "/img/img4-small.jpg",
"imgAlt": "Placeholder image",
"tags": [
"Design",
"Mobile",
"Responsive"
],
"date": 1367154709885,
"podStyle": {
"width": 253
}
}
]
(为了简短起见,我只展示了一个项目)。
一旦我完成循环并获得x和y数据,我想将其应用于podStyle
对象。我用以下数据调用setState()
:
[
{
"podStyle": {
"x": 0,
"y": 0,
"height": 146,
"width": 253
}
}
]
这似乎从模型中删除了所有当前数据,只留下podStyle
数据。我是不是误解了合并的原理?
如果你的状态是一个对象:
getInitialState: function() {
return { x: 0, y: 0 };
}
您可以使用setState
在该对象上设置单个键:
this.setState({ x: 1 }); // y still == 0
React不智能合并你的状态;例如,这行不通:
getInitialState: function() {
return {
point: { x: 0, y: 0 },
radius: 10
};
}
this.setState({point: {x: 1}});
// state is now == {point: {x: 1}, radius: 10} (point.y is gone)
[编辑]正如@ssorallen提到的,您可以使用不变性帮助器来获得您想要的效果:
var newState = React.addons.update(this.state, {
point: { x: {$set: 10} }
});
this.setState(newState);
请看这个JSFiddle的例子:http://jsfiddle.net/BinaryMuse/HW6w5/
合并是浅的,所以
this.setState({point})
保留(ed: this.state.radius)不变,但完全替换(ed: this.state.point)。https://facebook.github.io/react/docs/state-and-lifecycle.html state-updates-are-merged
从ES7+的角度来看已经给出的答案,使用transform-object-rest-spread代替Object.assign()
:
class MyComponent extends React.Component {
state = {
point: {
x: 0,
y: 0,
},
radius: 10,
}
handleChange = () => {
this.setState((prevState, props) => ({
point: {
// rest operator (...) expands out to:
...prevState.point, // x:0, y:0,
y: 1, // overwrites old y
},
// radius is not overwritten by setState
}));
}
render() {
// omitted
}
}
。Babelrc(也需要Babel预设阶段2的转换类属性)
{
"presets": ["es2015", "stage-2", "react"],
"plugins": ["transform-object-rest-spread"],
}
2018-04-22
更新正如@sheljohn指出的(谢谢!),在setState
中引用this.state
是不可靠的:
因为
this.props
和this.state
可能是异步更新的,所以你不应该依赖它们的值来计算下一个状态。…
要解决这个问题,使用
setState()
的第二种形式,它接受函数而不是对象。该函数将接收前一个状态作为第一个参数,并将应用更新时的道具作为第二个参数https://reactjs.org/docs/state-and-lifecycle.html state-updates-may-be-asynchronous
类似于
getInitialState: function() {
return {
something: { x: 0, y: 0 },
blah: 10
};
}
var state = Object.assign(this.state, {
something: Object.assign(this.state.something, { y: 50 }),
});
this.setState(state);
如果是递归/深度的,而不是硬编码树,那就更好了,但我将把这个留给读者:)
- 在循环中分配json值时,值被覆盖
- JQuery合并了keyup和focusout两个函数
- 谷歌地图固定位置覆盖
- 只覆盖箭头键滚动事件
- JSON重构(合并内容)与javascript
- JQuery覆盖不更改单选选项
- 如何覆盖锚点元素's href目标,并在我点击转到目标javascript时删除其他错误
- Javascript-根据赋值顺序,按键合并对象数组
- 合并两个数组,重新调整循环js
- 将添加一个相同类型的事件附加或覆盖以前添加的具有相同名称的事件
- 合并两个对象而不覆盖
- 合并两个 JavaScript 对象而不覆盖
- 合并深层对象并覆盖
- 在 JavaScript/jQuery 中覆盖/合并两个对象
- 合并JSON并覆盖值
- 合并两个对象,如果冲突,则覆盖值
- 将一个对象合并到另一个对象的最佳方式(无覆盖)
- React.js: setState覆盖,而不是合并
- 合并两个对象而不覆盖
- 合并JS对象而不覆盖