代码之家  ›  专栏  ›  技术社区  ›  Subham Tripathi

连续设置状态无法按预期工作

  •  1
  • Subham Tripathi  · 技术社区  · 7 年前

    我有以下代码-

    class Sum extends React.Component {
        constructor(props) {
          super(props)
          this.state = { a : 0 }
        }
    
        // let's call this ADD-1
        add = () => {
          this.setState({ a: this.state.a + 1 })
          this.setState({ a: this.state.a + 2 })
          this.setState({ a: this.state.a + 3 })
        } 
    
        render() {
          return (<div>
            <button onClick={this.add}> click me  </button>
            <div> sum  {this.state.a} </div>
          </div>)
        }
    }
    

    单击该按钮时渲染

    sum = 3
    

    正如我所希望的那样 sum = 6 即1+2+3

    另外,如果我改变我的 add 方法来适应 prevState 种族状况-

      // let's call this ADD-2
      add = () => {
        this.setState({ a: this.state.a + 1 })
        this.setState({ a: this.state.a + 2 })
        this.setState(prevState => ({ a: prevState.a + 1 }))
        this.setState(prevState => ({ a: prevState.a + 4 }))
      }
    

    它呈现 sum = 7 但我希望 sum = 8 即(1+2+1+4)

    现在我想到两个问题:

    1)为什么我们认为结果是上述结果,而不是我所期望的结果?

    2)为什么我看不到ui中加法的转换? 假设我们将方法标记为 ADD-1 ,我应该看到 sum = 1 然后 sum = 3 然后 总和=6 是的。是不是因为更新的批处理,但批处理将它们放入执行队列中,在我看来,它不会覆盖任何内容。

    4 回复  |  直到 7 年前
        1
  •  1
  •   Ragul Parani    7 年前

    状态更新可能是异步的。检查这个 answer 是的。

    在一个 answer dan abramov指出,一个事件调用中的状态更新只会在事件结束时产生一个重新呈现。

    无论在多少组件中调用了多少setState()函数 在react事件处理程序中,它们只生成一个 在事件结束时重新呈现。

    而且批处理只发生在react事件处理程序中的状态更新,即批处理不发生在ajax调用中

    promise.then(() => {
      // We're not in an event handler, so these are flushed separately.
      this.setState({a: true}); // Re-renders with {a: true, b: false }
      this.setState({b: true}); // Re-renders with {a: true, b: true }
      this.props.setParentState(); // Re-renders the parent
    });
    

    但通过将回调传递给 setState 方法

    add = () => {
          this.setState({ a: this.state.a + 1 },
            () => {
            this.setState({ a: this.state.a + 2 },
              () => {
              this.setState({ a: this.state.a + 3 })
            })
          })    
        }
    

    以上将返回sum=6。

    在设置状态中不使用回调时:

    PureComponent shouldComponentUpdate 可以用来调整 组件的性能。它们通过防止生命周期方法来工作 当道具和状态没有改变时开火。

    这个 设置状态 不管发生什么,都会触发回调 shouldcomponentupdate 返回。所以, 设置状态 回调将启动,即使状态没有 改变。

        2
  •  1
  •   WebbH    7 年前

    “为了提高性能,React可能会将多个setState()调用批处理到单个更新中。”

    Docs

        3
  •  1
  •   Tholle    7 年前

    确保将函数传递给 setState 当您的更新依赖于当前状态,因此不会被后续的 设置状态 是的。

    例子

    class App extends React.Component {
      state = { a: 0 };
    
      add = () => {
        this.setState(previousState => {
          return { a: previousState.a + 1 };
        });
        this.setState(previousState => {
          return { a: previousState.a + 2 };
        });
        this.setState(previousState => {
          return { a: previousState.a + 3 };
        });
      };
    
      render() {
        return (
          <div>
            <button onClick={this.add}> click me </button>
            <div> sum {this.state.a} </div>
          </div>
        );
      }
    }
    
        4
  •  0
  •   Poulima Biswas    7 年前

    状态更改只能通过setstate进行,但如果在setstate(this.state.a+1)之前访问并修改this.state,它将不会反映出来。所以每次你访问这个,state,a,它得到0,也就是初始值。

    add = () => {
      this.setState({ a: this.state.a + 1 }) // 0 + 1
      this.setState({ a: this.state.a + 2 }) // 0 + 2
      this.setState({ a: this.state.a + 3 }) // 0 + 3
    } 
    
    this.setState((previousState) => { // change state using previousState} );
    

    这是更新状态的方法