javascript - ReactJs:不可变数据

标签 javascript reactjs immutability

我正在学习官方的 ReactJs 教程,我开始对不变性的含义和应用感到困惑。

我的想法是这样的一个例子。想象一下我在构造函数中有一个对象 this.state = {dog: some data} 然后我调用一个设置 this.setState = {dog: another data} 的handleClick 函数>。由于我使用 setState 来更新值,旧的引用仍然是不可变的,我可以知道发生了什么变化。

但是在教程中,当他们使用 .slice() 复制“squares”状态以不更改原始数组,然后应用带有新值的 setState 时, 我很困惑。

为什么他们需要复制数组,他们不能在 setState 中引用它并在那里更改内容吗?原始引用文献仍然可追溯...

编辑:

@FelixKling 这里:

class Board extends React.Component {
  constructor() {
    super();
    this.state = {
       squares: Array(9).fill(null),
    };
  }

  handleClick(i) {
    const squares = this.state.squares.slice();
    squares[i] = 'X';
    this.setState({squares: squares});
  }
}

他们不能将其放入 setState 中,而不是复制初始数组吗?

最佳答案

这是一篇非常棒的文章,有助于解释为什么不变性很重要:http://reactkungfu.com/2015/08/pros-and-cons-of-using-immutability-with-react-js/

In fact, React.js does not need to have knowledge about what exactly changed. All it needs to know is whether the state changed at all or not.

While immutability does not provide easier answers to a what exactly changed problem, it provides a great answer to the is it changed at all or not question.

React,顾名思义,对状态的变化做出“ react ”,并随着状态的变化重新渲染组件。因此对于 React 来说,了解状态是否发生变化很重要,不幸的是,改变对象可能会导致比较变得困难。

考虑这个例子:

var a = 6; // numbers are primatives in javascript and compare by value
var b = 6; 
var c = a; // 6

// in this case 
a === b // true
b === c // true, 6

但是您不能对对象执行相同的操作,因为它们是通过引用进行比较的,也就是说它们指向内存中的同一点。

var objA = { name: 'Sally' };
var objB = { name: 'Sally' };
var objC = objA;

// these are not the same object
objA.name === objB.name // true, 'Sally'
objA === objB // false, they reference different objects even though the keys and values are the same
objA === objC // true, they reference the same point in memory

当您尝试修改值时,React 中出现的问题更容易说明。

让我们再次以数字为例并进行一些更改:

c = 14;
a === b // true, still 6, the value of 'a' is still 6
a === c // false, 6 ≠ 14

这使得我们改变了 c 的值,它现在应该不同了。现在让我们修改我们的对象。

objA.age = 30; // give objA an age property    
objB.age = 35; // give objB an age property
objC.age = 40; // give objC an age property, actually changes objA

// now try equality
objA === objB // false, we already know this
objA.age === objB.age // false, as expected
objA.age === objC.age // true, possibly unexpected as it looks like we are comparing 30 to 40, but in fact our change to objC modified objA
objA === objC // true both have age set to 40

因此,如果我们每次都给 React 一个新的状态,而不是改变它,那么就更容易知道它是否应该重新渲染。

那么您可能想知道,为什么 React 不只存储状态的副本并将其与变异状态进行比较。也许你并不奇怪这一点,但这似乎是 React/Redux 可以处理的事情,然后我们可以自由地改变状态,让我们变得更容易。

事实证明,比较两个对象是一项相当密集的任务,首先你必须确保它们都有相同的键,并且这些键保存相同的值 - 看起来并不难 - 但然后你意识到对象可以包含许多其他嵌套对象,并且这种比较变得递归,检查每个嵌套对象。

传递一个新的状态会更容易,这样 React 就能立即知道它已经改变了。

除此之外,生成新状态还允许您通过跟踪和存储以前的状态(如果您愿意)来进行“时间旅行”。

关于javascript - ReactJs:不可变数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44012420/

相关文章:

javascript - jQuery 如何更改第二个元素上的文本?

javascript - .load() 使所有ajax加载的div刷新

javascript - 如何动态更改 href 属性

java - Spring 应用程序中通过 ReactJS REST 生成的文件列表为空

javascript - 用于将 HTML block 传递给 React 组件的全局 JS 变量

java - Guava 的 FluentIterable 线程安全

javascript - 通过刷多路径图表无法绘制 d3.js Focus+Context

javascript - 导入的 json 数据分配给现有状态不起作用

unit-testing - 如何在没有模拟的情况下记录/验证单元测试中的方法调用?

python - 在 stackless python 中,通过 channel 发送的数据是不可变的吗?