React未从数组内的对象更新属性
React not updating property from an object inside an array
我想做的是动态添加新元素,并在未来的某个时候更改它们的样式。为此,我尝试创建一个对象,该对象将进入状态,并包含两个设置了数组值的属性:一个是保存元素本身的数组,另一个保存与之相关的样式。
但出于某种原因,即使我尝试创建一个包含这两个属性的对象的副本(有人说,将状态视为stackoverflow上的不可变状态)并更新它,然后将状态设置为新对象,它似乎仍然没有更新。
我也尝试过这个解决方案,但它仍然会出现同样的问题。
var React = require('react');
var ReactDOM = require('react-dom');
var update = require('react-addons-update');
var Book = React.createClass({
getInitialState() {
return {
pages: {
pageElements: [], pageStyle: []
}
};
},
changeStyle: function (e) {
this.setState(update(this.state.pages.pageStyle[0],
{name: {$set: {position: 'absolute', transform: 'translate(50px,100px)'} }}));
},
componentDidMount: function () {
let pagesCopy = {
pageElements: this.state.pages.pageElements, pageStyle: []
};
pagesCopy.pageStyle.push({styles: {position: 'absolute'}});
pagesCopy.pageElements.push(
<img
key={0}
onMouseDown={this.changeStyle}
style={this.state.pages.pageStyle[0]}
src={'/pages/0'}
height="800px"
width="600px"/>);
this.setState({pages: pagesCopy});
},
render: function () {
return (
<div>
<section style={{position: 'relative', height:800, width:1200, margin: 'auto'}}>
{this.state.pages.pageElements}
</section>
</div>
)
}
});
ReactDOM.render(<Book/>, document.getElementById("content"));
我认为问题在于以下几点:
style={this.state.pages.pageStyle[0]}
它直接引用对象。我认为它将这个值永久地设置为样式,因为只能有状态的副本,所以它看不到持有这两个属性的新对象上的更新值。我还研究了如何获得对数组索引的引用,以便它在每次更新状态时都会获取它,但最终,它只是使该值成为最终值并保持静态(我认为)。
注意:该代码是一个更大代码的超级简化版本,但我这里的代码是导致问题的基本代码
首先,我想指出您的代码中有一些我认为是拼写错误的地方。在componentDidMount()
中,您在推入pagesCopy
的img
组件上设置以下道具:
style={this.state.pages.pageStyle[0]}
由于this.state.pages.pageStyle
在当时是一个空数组,我相信你的意思是设置道具如下:
style={pagesCopy.pageStyle[0]}
一旦解决了这个问题,我认为你已经正确地诊断出了直接原因。也就是说,您存储在this.state.pages.pageElements[0]
中的img
组件包含对对象的引用(pagesCopy.pageStyle[0]
,后来成为this.state.pages.pageStyle[0]
)。当您调用changeStyles()
时,您正在创建一个新对象,而不是更改旧对象。这是一个问题,因为img
组件上的样式道具仍然包含对旧对象的引用,而旧对象没有更改。
如果您需要在紧急情况下进行此操作,我的建议是在changeStyles()
方法中直接更改this.state.pages.pageStyle[0]
中的对象,然后调用forceUpdate()
。调用forceUpdate()
将导致重新渲染。img
组件将重新渲染,其样式道具将包含对具有新属性值的旧对象的引用。下面的代码可以做到这一点:
changeStyle: function() {
var styles = this.state.pages.pageStyle[0];
styles.position = 'absolute';
styles.transform = 'translate(50px,100px)';
this.forceUpdate();
}
现在,我要强调的是,这是非常非常糟糕的做法。直接改变状态几乎总是个坏主意。如果有充分的理由这么做的话,我还没有听说。
以下是如何在不直接改变状态的情况下做到这一点的建议。
var Book = React.createClass({
getInitialState() {
return {
pageElements: [
{
tagName: 'img',
props: {
src: 'http://www.keenthemes.com/preview/metronic/theme/assets/global/plugins/jcrop/demos/demo_files/image1.jpg',
height: '800px',
width: '600px',
style: {
position: 'absolute'
}
}
}
]
};
},
changeStyle: function(e) {
this.setState(function(previousState) {
var newState = _.extend({}, previousState);
newState.pageElements[0].props.style = {
position: 'absolute',
transform: 'translate(50px,100px)'
};
return newState;
});
},
render: function () {
return (
<div>
<section style={{ position: 'relative', height: 800, width: 1200, margin: 'auto' }}>
{
this.state.pageElements.map(function(pageElement, index) {
return React.createElement(pageElement.tagName,
_.extend(pageElement.props, {
key: index,
onMouseDown: this.changeStyle.bind(this)
})
);
}.bind(this))
}
</section>
</div>
);
}
});
React.render(<Book/>, document.getElementById('content'));
- 从knockout.js中的另一个对象更新一个深度结构化的javascript对象
- Meteor使用对象更新集合
- 如何使用不同视图的JSON对象更新angular js中的全局JSON字段
- 流星反应式嵌套对象更新父对象
- 从返回的 MongoDB 对象更新 Angular.js $scoped
- 在节点 JS 中将值从一个对象更新到另一个对象
- 使用循环从另一个对象更新对象
- React未从数组内的对象更新属性
- 可以't使用新对象更新localStorage
- 使用MongoDB,如何使用变量中的对象更新数组中的对象
- 从用PHP脚本创建的json对象更新速度表数据
- mongoDB-使用$set和一个对象更新文档
- 无法使用新数据对象更新Knockout UI
- 通过REST端点用JSON对象更新Mongoose架构
- 变量引用对象的值,但在对象更新时不更新
- 如何使用jq命令行实用程序执行JSON对象更新
- ReactJS皮质对象更新渲染未调用
- 如何使用json对象更新dojo网格
- 使用接收到的对象更新css设置
- 只有一些我的解析对象更新(总是9,但没有更多),当我运行这个javascript解析云代码