反应中引用状态

时间:2017-10-01 23:55:52

标签: javascript reactjs

保持对特定(或“活动”)对象的引用是我在许多情况下使用的模式,用于更改对象数组中的特定对象(或者你有什么)。

  state = {
  object1: { 'data': 'data1'},
  active_object: null,
}

// point active_object to object1
state.active_object = state.object1;

// modify it through the reference
state.active_object.data = 'data1modified';

// works as expected
console.log('object1.data: ' + state.object1.data);

现在反应组件状态中的等价物将沿着这些线(注意这是非工作的)。我认为引用会在“翻译的某个地方”丢失。是否有(简单)方式来模仿上面的模式(除了重组,使用对象键等)使用react和state来完成同样的事情?

class App extends Component {
  constructor() {
    super()
    this.state = {
      active_object: null,
      object1: { 'data': 'data1'},
    }
  }

  modifyState() {
    // point active_object to object1 (using *functional* setState)
    this.setState((state) => (
      { active_object: state.object1 }
    ))

    // modify it through the reference (using *functional* setState)
    this.setState((state) => (
      { active_object: { ...state.active_object, ['data']: 'data1modified' } }
    ))
  }

  render() {
    return (
      <div className="App">
        <p onClick={ () => this.modifyState() }>modify</p>
        <p>{ this.state.object1.data }</p>
      </div>
    );
  }

}
编辑:我已经更新了示例,使用构造函数来混淆人们(我正在使用babel,所以现实中并不需要)。另外,我在评论中更清楚地表明我正在使用功能性 setState(同样,不要让人混淆)。我需要澄清一点,我不需要帮助让这些特定的代码工作,它更多的是展示我希望能够做什么。在这方面,它伪代码即使你在反应中运行它实际上工作正常(除了参考丢失,正如预期的那样)。

EDIT2:正如vs1682在对这个问题的评论中指出的那样,在复制对象时使用对象扩展运算符会丢失引用。所以这个问题并没有真正具体反应(只是间接地)。

2 个答案:

答案 0 :(得分:0)

也许这是一个令人震惊的错字,但你没有FooBar。如果你不明白为什么需要它,也许你应该回到基础知识并阅读一下JavaScript ES6。

constructor

constructor(props) { super(props) this.state = { active_object: null, object1: { 'data': 'data1'}, } } 不接受回调作为其主要参数......或者至少这不是约定。 this.setState可以接受回调作为辅助参数,但这是为了处理this.setState的异步性质。它没有明确地改变状态。

this.setState

此外,JavaScript惯例高度鼓励camelCase,而不是下划线。

编辑:我错了。可以在this.setState({ active_object: this.state.object1 }) 中使用函数。事实上,这可能是个不错的主意。

答案 1 :(得分:0)

如果您在同一对象中引用属性(例如问题中的情况),则可以使用例如clone执行深层复制。那将&#34;重新链接&#34; (我不确定这里的术语)引用即使返回一个带有新内容的新对象。

我用这种方法看到的唯一缺点是,不会保留到达您正在克隆的对象的的引用,而在浅层副本中(对象传播的内容)因为它根本不会修改参考文献,所以它会变成不可变形的帮助者。这个具体问题可能与clone有关。

无论如何,这是有效的,但我不知道性能的影响,或者考虑到反应和状态的功能性,它是不是很好的做法。

import React, { Component } from 'react';
import clone from 'clone';

class App extends Component {
  constructor() {
    super()
    this.state = {
      activeObject: null,
      object1: { 'data': 'data1'},
    }
  }

  modifyState() {
    // point activeObject to object1
    this.setState((state) => {
      let newState = clone(state);
      newState.activeObject = newState.object1;
      return newState;
    })
    // modify it through the reference
    this.setState((state) => {
      let newState = clone(state);
      newState.activeObject.data = 'data1-modified';
      return newState;
  })
  }

  render() {
    return (
      <div className="App">
        <p onClick={ () => this.modifyState() }>modify</p>
        {/* will show 'data1-modified' after modifyState */}
        <p>{ this.state.object1.data }</p>
      </div>
    );
  }

}

应该说带引用的克隆对象总是很棘手,并且需要更多的时间而不是你设置一个特殊的方法(特定于复制对象或数据结构)而不是依赖仅浅层/深层复制。在我的情况下,我认为&#34;正常&#34;浅拷贝和恢复引用的处理程序将是最好的方法。

或者,完全跳过引用,并依赖于唯一对象属性(例如和&#34; active&#34;标识符或&#34; id&#34;)来替换此方案中的麻烦参考。我怀疑在依赖于不可变状态的反应模型的值(和不变性)复制的语言中,由于缺少(不总是,但经常)对象/值引用,这不是一个问题。