Javascript 为什么可以';直接修改组件';真的吗?

Javascript 为什么可以';直接修改组件';真的吗?,javascript,reactjs,Javascript,Reactjs,我理解React教程和文档警告在该状态下不应直接变异,所有内容都应通过setState currentStateCopy.push(6) this.setState({ a: currentStateCopy }) 我想知道为什么我不能直接改变状态,然后(在同一个函数中)调用this.setState({})来触发渲染 例如:下面的代码似乎工作得很好: const React = require('react'); const App = React.createClass({

我理解React教程和文档警告在该状态下不应直接变异,所有内容都应通过
setState

currentStateCopy.push(6)
this.setState({
  a: currentStateCopy
})
我想知道为什么我不能直接改变状态,然后(在同一个函数中)调用
this.setState({})
来触发
渲染

例如:下面的代码似乎工作得很好:

const React = require('react');

const App = React.createClass({
    getInitialState: function() {
        return {
            some: {
                rather: {
                    deeply: {
                        embedded: {
                            stuff: 1
                        }}}}};
    },
    updateCounter: function () {
        this.state.some.rather.deeply.embedded.stuff++;
        this.setState({}); // just to trigger the render ...
    },
    render: function() {
        return (
                <div>
                Counter value: {this.state.some.rather.deeply.embedded.stuff}
                <br></br>
                <button onClick={this.updateCounter}>inc</button>
                </div>
        );
    }
});

export default App;
const React=require('React');
const App=React.createClass({
getInitialState:函数(){
返回{
一些:{
而是:{
深深地:{
嵌入式:{
资料:1
}}}}};
},
updateCounter:函数(){
this.state.some.property.deep.embedded.stuff++;
this.setState({});//只是为了触发渲染。。。
},
render:function(){
返回(
计数器值:{this.state.some.pretty.deep.embedded.stuff}


股份有限公司 ); } }); 导出默认应用程序;
我完全支持以下约定,但我想进一步了解ReactJS实际上是如何工作的,以及上面的代码会出现什么问题或是次优

下面的注释基本上确定了两个问题:

  • 如果您直接对状态进行变异,然后随后调用
    this.setState
    ,则可能会替换(覆盖?)您所做的变异。在上面的代码中,我看不出这是如何发生的
  • setState
    可能以异步/延迟的方式有效地变异
    this.state
    ,因此在调用
    this.setState
    后立即访问
    this.state
    时,不能保证访问最终的变异状态。我明白了,如果
    this.setState
    是update函数的最后一次调用,那么这不是问题
  • 可以这样说:

    切勿直接对该状态进行变异
    ,因为之后调用
    setState()
    可能会替换您进行的变异。将
    此.state
    视为是不可变的

    setState()
    不会立即改变此.state,但会创建挂起的状态转换。调用此方法后访问
    this.state
    ,可能会返回现有值

    无法保证对
    setState
    的调用的同步操作,并且可能会对调用进行批处理以提高性能

    setState()
    将始终触发重新渲染,除非在
    shouldComponentUpdate()
    中实现了条件渲染逻辑。如果正在使用可变对象,并且逻辑无法在
    shouldComponentUpdate()
    中实现,则仅当新状态与以前状态不同时调用
    setState()
    将避免不必要的重新渲染

    基本上,如果您直接修改
    this.state
    ,就会造成这些修改可能被覆盖的情况


    与您的扩展问题1)和2)相关,
    setState()
    不是即时的。它根据它认为正在发生的情况对状态转换进行排队,其中可能不包括对
    this.state
    的直接更改。由于它是排队的,而不是立即应用的,所以完全有可能在这两者之间修改了某些内容,从而覆盖了您的直接更改


    如果没有其他问题,您最好考虑不直接修改
    this.state
    可以被视为良好实践。您个人可能知道,您的代码与React的交互方式不会出现这些过度编写或其他问题,但您正在创建一种情况,其他开发人员或未来的更新可能会突然发现自己有奇怪或微妙的问题。

    我目前的理解基于以下内容:

    如果没有使用
    应组件更新
    或任何其他生命周期方法(如
    组件将接收道具
    组件将更新
    ,以及
    组件更新
    )来比较新旧道具/状态

    然后

    改变
    状态
    ,然后调用
    setState()
    ,这样做很好,否则就不好。

    这个答案是为了提供足够的信息,不直接在React中改变/改变状态。 反应如下。也就是说,react内部的数据流应该并且将被预期为循环路径

    React的无流量数据流

    为了使React像这样工作,开发人员让React类似于函数式编程。函数式编程的经验法则是不变性。让我解释清楚

    单向流是如何工作的?

    • 状态
      是包含组件数据的数据存储
    • 组件的
      视图
      基于状态进行渲染
    • 视图
      需要更改屏幕上的某些内容时,该值应该由
      存储提供
    • 为了实现这一点,React提供了
      setState()
      函数,该函数接收新
      状态的
      对象
      ,并对以前的状态进行比较和合并(类似于
      object.assign()
      ),并将新状态添加到状态数据存储中
    • 每当状态存储区中的数据发生更改时,react将触发重新呈现
      视图使用的新状态,并将其显示在屏幕上
    该循环将在组件的整个寿命期内持续

    如果您看到上面的步骤,它清楚地显示了当您更改状态时许多事情正在发生。因此,当您直接改变状态并使用
    // same as 
    this.state.a.push(6)
    this.setState({})
    
    // original state
    this.state = {
      a: [1,2,3,4,5]
    }
    
    // changing the state in react
    // need to add '6' in the array
    
    // create a copy of this.state.a
    // you can use ES6's destructuring or loadash's _.clone()
    const currentStateCopy = [...this.state.a]
    
    currentStateCopy.push(6)
    this.setState({
      a: currentStateCopy
    })
    
    import update from 'immutability-helper';
    
    const newData = update(myData, {
      x: {y: {z: {$set: 7}}},
      a: {b: {$push: [9]}}
    });