Javascript React不从数组中的对象更新属性
我想做的是动态添加新元素,并在将来某个时候更改它们的样式。为此,我尝试创建一个对象,该对象将进入状态,并包含两个属性,这些属性设置了一个数组值:一个是保存元素本身的数组,另一个保存与该元素相关联的样式 但出于某种原因,即使我尝试创建一个包含这两个属性的对象副本(有人说要将状态视为在stackoverflow上是不可变的)并对其进行更新,然后将状态设置为新对象,它似乎仍然没有更新 我也尝试了来自的解决方案,但它仍然给出了相同的问题Javascript React不从数组中的对象更新属性,javascript,reactjs,Javascript,Reactjs,我想做的是动态添加新元素,并在将来某个时候更改它们的样式。为此,我尝试创建一个对象,该对象将进入状态,并包含两个属性,这些属性设置了一个数组值:一个是保存元素本身的数组,另一个保存与该元素相关联的样式 但出于某种原因,即使我尝试创建一个包含这两个属性的对象副本(有人说要将状态视为在stackoverflow上是不可变的)并对其进行更新,然后将状态设置为新对象,它似乎仍然没有更新 我也尝试了来自的解决方案,但它仍然给出了相同的问题 var React = require('react'); var
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"));
它直接引用对象的位置。我认为它会将该值永久地设置为样式,并且由于只能有状态的副本,因此它无法在包含这两个属性的新对象上看到更新的值。我还讨论了如何获取对数组索引的引用,以便它在每次更新状态时都会获取它,但最终,它只是将该值设置为final并使其保持静态(我认为)
注意:该代码是一个更大代码的超级简化版本,但我这里的代码是导致问题的基本代码。首先,我想指出您的代码中有一些我认为是打字错误的地方。在
componentDidMount()
中,您在推入pageScope
的img
组件上设置以下道具:
style={this.state.pages.pageStyle[0]}
由于当时this.state.pages.pageStyle
是一个空数组,我相信您的意思是按如下方式设置道具:
style={pagesCopy.pageStyle[0]}
一旦解决了这个问题,我想你已经正确地诊断出了近因。也就是说,您存储在this.state.pages.pageElements[0]
中的img
组件包含对对象的引用(pageScope.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'));
var Book=React.createClass({
getInitialState(){
返回{
页面元素:[
{
标记名:“img”,
道具:{
src:'http://www.keenthemes.com/preview/metronic/theme/assets/global/plugins/jcrop/demos/demo_files/image1.jpg',
高度:“800px”,
宽度:“600px”,
风格:{
位置:'绝对'
}
}
}
]
};
},
更改样式:函数(e){
this.setState(函数(previousState){
var newState=..extend({},previousState);
newState.pageElements[0]。props.style={
位置:'绝对',
转换:“转换(50px,100px)”
};
返回新闻状态;
});
},
渲染:函数(){
返回(
{
this.state.pageElements.map(函数(pageElement,索引){
返回React.createElement(pageElement.tagName,
_.extend(pageElement.props{
关键词:索引,,
onMouseDown:this.changeStyle.bind(this)
})
);
}.绑定(本)
}
);
}
});
React.render(,document.getElementById('content'));
首先,我想指出您的代码中有一些我认为是打字错误的地方。在componentDidMount()
中,您在推入pageScope
的img
组件上设置以下道具:
style={this.state.pages.pageStyle[0]}
由于当时this.state.pages.pageStyle
是一个空数组,我相信您的意思是按如下方式设置道具:
style={pagesCopy.pageStyle[0]}
一旦解决了这个问题,我想你已经正确地诊断出了近因。也就是说,您存储在this.state.pages.pageElements[0]
中的img
组件包含对对象的引用(pageScope.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();
}
现在,我要强调,这是非常非常糟糕的做法。直接改变状态几乎总是个坏主意。如果有好的理由