React不从数组内的对象更新属性

时间:2015-12-26 03:52:19

标签: javascript reactjs

我尝试做的是动态添加新元素并在将来某个时候更改其样式。所以要做到这一点,我尝试创建一个进入状态的对象,并且将包含两个具有设置为它们的数组值的属性:一个是保存元素本身的数组,另一个是保存与之关联的样式的数组。

但由于某种原因,即使我尝试创建一个包含两个属性的对象的副本(有人说将状态视为在stackoverflow上不可变)并更新它,然后将状态设置为新对象,它似乎还没有更新。

我也尝试过来自here的解决方案,但它仍然会出现同样的问题。

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]}

它直接引用对象的地方。我认为它采用了这个值并永久地将该值设置为样式,因为只能存在状态副本,所以它无法看到保存这两个属性的新对象的更新值。我还做了research关于如何获取对数组索引的引用,以便每当我更新状态时它都会获取它,但最终,它最终只是使该值最终并保持静态(我认为)

注意:代码是更大代码的超级简化版本,但我在这里的代码是造成问题的基本代码

1 个答案:

答案 0 :(得分:0)

首先,我想在您的代码中指出我认为是拼写错误的内容。在componentDidMount()中,您在推送到img的{​​{1}}组件上设置了以下道具:

pagesCopy

由于当时style={this.state.pages.pageStyle[0]}是一个空数组,我相信你的意思是按如下方式设置道具:

this.state.pages.pageStyle

一旦修复,我认为你已经正确地诊断了原因。也就是说,您存储在style={pagesCopy.pageStyle[0]}中的img组件包含对对象的引用(this.state.pages.pageElements[0],后来变为pagesCopy.pageStyle[0])。当您调用this.state.pages.pageStyle[0]时,您正在创建一个新对象而不是改变旧对象。这是一个问题,因为changeStyles()组件上的样式prop仍包含对旧对象的引用,该引用未更改。

如果你需要在紧张的情况下完成这项工作,我的建议是直接在img方法的this.state.pages.pageStyle[0]中改变对象,然后调用changeStyles()。调用forceUpdate()将导致重新渲染。 forceUpdate()组件将重新渲染,其样式prop将包含对具有新属性值的旧对象的引用。以下代码可以解决这个问题:

img

现在,我要强调这是非常非常糟糕的做法。直接变异状态几乎总是一个坏主意。如果有充分的理由这样做,我还没有听说过。

以下是关于如何在不直接改变状态的情况下执行此操作的建议。

changeStyle: function() {
  var styles = this.state.pages.pageStyle[0];
  styles.position = 'absolute';
  styles.transform = 'translate(50px,100px)';
  this.forceUpdate();
}