修改位于State中的对象属性

时间:2017-08-09 06:31:23

标签: reactjs

我已经了解到,为了修改位于state中的属性或子对象,不能直接在setState中设置它。相反,我需要在我的函数中创建对象的副本并首先在那里修改它。我当时正在做的是使用setState返回整个更改对象,如下所示:

constructor(props) {
    super(props)
        this.state = {
            item: this.props.item,
            success: false
        }
}

handleChange(event){
    let item = this.state.item;

    const target = event.target;
    let value = target.type === 'checkbox' ? target.checked : target.value;
    const id = target.id;

    item[id] = value;

    this.setState({
        item: item,
        success: true
    })
}
然而,我没有意识到的一件事是通过引用复制对象。这意味着行item[id] = value会自动更新状态。从setState函数中删除item: item行有什么危害吗?

    this.setState({
        success: true
    })

问题1:它的效果很好,但这样做会有副作用吗?

问题2:另一方面,保持原始setState的方式是否有任何损害?由于item已经在状态中更新,因此再次更新它似乎不会有任何损害。

问题3:首先制作一个完整的对象副本更有意义,因此避免出现如下问题:

let item = JSON.parse(JSON.stringify(this.state.item));

2 个答案:

答案 0 :(得分:2)

  

我已经了解到,为了修改位于state中的属性或子对象,不能直接在setState中设置它。相反,我需要在我的函数中创建对象的副本并首先在那里进行修改。

你没有被迫这样做。这是一种常见的做法,因为这样你可以使用浅比较来知道什么时候发生了变化并优化了渲染性能。我强烈建议你阅读官方指南的这些段落,以了解我在说什么:

那说:

  然而,我没有意识到的一件事是通过引用复制对象。这意味着订单项[id] =值会自动更新状态   问题1:这样做很好,但这样做会有副作用吗?

通过引用复制对象,是的,因此item[id] = value会更改状态值。但不会自动触发重新呈现您的组件。因此,状态发生了变化,但您的观点并未反映出这种变化。它适用于您的情况,因为在该指令之后,您调用setState,这是一个更改状态的函数(再次)触发重新渲染。如果您之后没有(或不需要)致电setState,则需要致电this.forceUpdate()以触发重新呈现,您的观看次数将反映出来“手动”状态改变。

  

问题2:另一方面,保持原始setState的方式是否有任何损害?由于项目已经在状态下更新,因此再次更新它似乎不会有任何损害。

这个问题在这一点上毫无意义。现在应该清楚发生了什么。

  

问题3:首先制作一个完整的对象副本更有意义,因此避免了整个问题,如下面的

对我以前链接过的手册中的内容有所了解。但是,使用JSON编码制作对象的副本是没有用的。有更好的方法,在链接中描述。

希望我很清楚,乐于助人!

答案 1 :(得分:0)

我建议你this article。除此之外,您可以使用const item = { ...this.state.item }而不是对该对象进行字符串化和解析。如果您注意到这一点,我已使用const代替let。在您尝试使用新值更改整个变量之前,const定义会很好。我的意思是,只要更新作为对象的const变量的属性,它就没问题了。

根据可变反应状态,我说它不理想。因为React检查变量引用。在您的情况下,参考不会改变。但是由于success,虚拟DOM会有所不同。