我对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数据。我误解了这种合并是如何运作的吗?
提前感谢您的帮助!
答案 0 :(得分:67)
如果你的州是一个对象:
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所述,您可以使用the immutability helpers来获得您之后的效果:
var newState = React.addons.update(this.state, {
point: { x: {$set: 10} }
});
this.setState(newState);
答案 1 :(得分:18)
合并很浅,因此
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
使用transform-object-rest-spread而不是Object.assign()
提供已给出答案的ES7 +观点:
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阶段的transform-class-properties)
{
"presets": ["es2015", "stage-2", "react"],
"plugins": ["transform-object-rest-spread"],
}
正如@sheljohn指出的那样(谢谢!),引用this.state
内的setState
是不可靠的:
由于
this.props
和this.state
可能会异步更新,因此您不应该依赖它们的值来计算下一个状态。...
要修复它,请使用第二种形式的
setState()
接受函数而不是对象。该函数将接收先前的状态作为第一个参数,并将更新应用的道具作为第二个参数https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
答案 2 :(得分:4)
类似的东西:
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);
如果它是递归/深度而不是硬编码树会更好,但我会把它留给读者:)