2017-05-16 19 views
0

我正在做官方的ReactJs教程,我开始对不变性的含义和应用感到困惑。ReactJs:不可变的数据

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

但在本教程中,当他们将.slice()的“正方形”状态复制为不更改原始数组,然后将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内,而不是复制初始数组?

+0

*“他们不能在setState中引用它,并在那里改变它”*你是什么意思?你能提供一个他们所做的和你认为他们应该做什么的具体例子吗? –

+0

请编辑您的问题,包括代码并正确格式化。评论中不可读。 –

+0

@FelixKling编辑了最高职位。 – orochamartins

回答

0

有点教程他们详细不变性的重要性进一步下跌: https://facebook.github.io/react/tutorial/tutorial.html#why-immutability-is-important

您还可以阅读了很多关于不变性这里:https://facebook.github.io/immutable-js/

不可变JS是一个图书馆的Facebook的对象不变性

创建

TLDR链接:跟踪更改和更容易确定何时重新渲染基本上更容易。

有关评论编辑:

所以你是正确的,this.setState会更新的对象,而不是变异它。

在这个例子中,我们创建了一个副本而不是变异。

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

在这个例子中,我们发生变异,而不是创建副本

handleClick(i) { 
    this.state.squares[i] = this.state.xIsNext ? 'X' : 'O'; 
    this.setState({ 
    squares: squares, 
    }); 
} 

对于我们并没有发生变异,阵营通过其生命周期事件时运行的第一个例子this.setState被称为并得到后到shouldComponentUpdate,这里会发生什么

shouldComponentUpdate(nextProps, nextState) { 
    // this will return true and trigger an update 
    return this.state.squares !== nextState; 
} 

对于第二个例子,我们做了变异,这里会发生什么:

shouldComponentUpdate(nextProps, nextState) { 
    // this will return false and will not trigger an update 
    return this.state.squares !== nextState; 
} 

现在,尽管我们已经改变了我们的国家,因为我们现在的,突变的状态是一样的我们的下一个状态(this.setState集)我们的反应组件将不会更新。

+0

我理解这个意思,我的疑问是在应用程序部分中,如果我在构造函数状态中放入一些对象,然后用函数中的对象更新的“setState”更新该对象但没有变异我对这部分感到困惑 – orochamartins

+0

I增加了一些关于不变异的重要性的解释。让我知道如果它清除它。 – JacobW

+0

感谢您的解释。因此,如果我们这样做了: 'handleClick(i){this.setState {{this.state.squares [i] = this.state.xIsNext?'X':'O', }); }' 我们将覆盖原始状态,React会将其解释为setState中的“未做任何更改”? – orochamartins

2

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

事实上,React.js并不需要有知识约究竟是什么改变了。所有它需要知道的是状态是否完全改变或不是

虽然不变性不提供答案,更容易向究竟是什么改变了问题,它提供了一个很好的答案的是它改变了所有或不问题。

反应,顾名思义'对'状态的变化作出'反应',并且会随着状态的改变而重新呈现组件。所以对于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/Redux可以处理的事情,然后我们可以自由地改变状态,使我们更容易。

事实证明,比较两个对象是一项相当艰巨的任务,首先您必须确保它们都具有相同的密钥,并且这些密钥具有相同的值 - 似乎并不困难 - 但您意识到对象可以包含许多其他嵌套对象,并且此比较将成为递归,检查每个嵌套对象。

只需通过一个新的状态就会容易得多,这样React就可以立即知道它已经改变了。

最重要的是,生成一个新状态还允许您通过跟踪并存储之前的状态来“时间旅行”,如果您选择。