在 React 组件中多次使用 this.setState 时会发生什么?

2022-08-30 04:33:51

我想检查当你多次使用this.setState时会发生什么(为了讨论起见,2次)。我以为组件将渲染两次,但显然它只渲染一次。我的另一个期望是,也许对setState的第二次调用将运行在第一个调用上,但你猜对了 - 工作正常。

链接到 JSfiddle

var Hello = React.createClass({
  render: function() {
    return (
      <div>
        <div>Hello {this.props.name}</div>
        <CheckBox />
      </div>
    );
  }
});

var CheckBox = React.createClass({
  getInitialState: function() {
    return {
      alex: 0
    };
  },

  handleChange: function(event) {
    this.setState({
      value: event.target.value
    });
    this.setState({
      alex: 5
    });
  },

  render: function() {
    alert('render');
    return (
      <div>
        <label htmlFor="alex">Alex</label>
        <input type="checkbox" onChange={this.handleChange} name="alex" />
        <div>{this.state.alex}</div>
      </div>
    );
  }
});

ReactDOM.render(
  <Hello name="World" />,
  document.getElementById('container')
);

如您所见,每次渲染都会弹出一个提示“渲染”。。.

你有解释为什么它能正常工作吗?


答案 1

React 批处理事件处理程序和生命周期方法中发生的状态更新。因此,如果您在处理程序中多次更新状态,React 将等待事件处理完成,然后再重新渲染。<div onClick />

需要明确的是,这仅适用于 React 控制的合成事件处理程序和生命周期方法。例如,状态更新不会在 AJAX 和事件处理程序中批处理。setTimeout


答案 2

setState() 方法不会立即更新组件的状态,它只是将更新放在队列中供以后处理。React 可以将多个更新请求批处理在一起,以使渲染更加高效。因此,当您尝试根据组件以前的状态更新状态时,必须采取特殊的预防措施。

例如,下面的代码只会将 state value 属性递增 1,即使它被调用了 4 次:

 class Counter extends React.Component{
   constructor(props){
     super(props)
    //initial state set up
     this.state = {value:0}
   }
   componentDidMount(){
    //updating state
    this.setState({value:this.state.value+1})
    this.setState({value:this.state.value+1})
    this.setState({value:this.state.value+1})
    this.setState({value:this.state.value+1})
   }
   render(){
    return <div>Message:{this.state.value}</div>
   }
}

为了在更新状态后使用状态,请在回调参数中执行所有逻辑:

//this.state.count is originally 0
this.setState({count:42}, () => {
  console.log(this.state.count)
//outputs 42
})

setState(updater,[回调])方法可以将更新程序函数作为其第一个参数,以基于以前的状态和属性更新状态。更新程序函数的返回值将与以前的组件状态浅层合并。该方法异步更新状态,因此有一个选项回调,一旦状态完全完成更新,就会调用该回调。

例:

this.setState((prevState, props) => { 
return {attribute:"value"}
})

下面是如何根据以前的状态更新状态的示例:

    class Counter extends React.Component{
      constructor(props) {
        super(props)
    //initial state set up
        this.state = {message:"initial message"}
    }
      componentDidMount() {
    //updating state
        this.setState((prevState, props) => {
          return {message: prevState.message + '!'}
        })
     }
     render(){
       return <div>Message:{this.state.message}</div>
     }
  }