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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33613728/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 15:16:45  来源:igfitidea点击:

What happens when using this.setState multiple times in React component?

javascriptreactjs

提问by alexunder

I wanted to check what happens when you use this.setState multiple times (2 times for the sake of the discussion). I thought that the component will be rendered twice but apparently it's rendered only once. Another expectation I had was that maybe the second call for setState will run over the first one, but you guessed it - worked fine.

我想检查多次使用 this.setState 时会发生什么(为了讨论,两次)。我认为该组件将被渲染两次,但显然它只被渲染一次。我的另一个期望是 setState 的第二次调用可能会超过第一个,但您猜对了 - 工作正常。

Link to a JSfiddle

链接到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')
);

As you'll see, an alert that says 'render' pops up on every render.

正如您将看到的,每次渲染时都会弹出一个提示“渲染”。

Do you have an explanation for why it worked properly?

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

回答by Chris Gaudreau

React batches state updates that occur in event handlers and lifecycle methods. Thus, if you update state multiple times in a <div onClick />handler, React will wait for event handling to finish before re-rendering.

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

To be clear, this only works in React-controlled synthetic event handlers and lifecycle methods. State updates are not batched in AJAX and setTimeoutevent handlers, for example.

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

回答by Biboswan

The setState() method does not immediately update the state of the component, it just puts the update in a queue to be processed later. React may batch multiple update requests together to make rendering more efficient. Due to this, special precautions must be made when you try to update the state based on the component's previous state.

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

For example, the following code will only increment the state value attribute by 1 even though it was called 4 times:

例如,以下代码只会将状态值属性增加 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>
   }
}

In order to use a state after it has been updated, do all logic in the callback argument:

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

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

The setState(updater,[callback]) method can take in an updater function as its first argument to update the state based on the previous state and properties. The return value of the updater function will be shallowly merged with the previous component state. The method updates the state asynchronously, so a there is an option callback that will be called once the state has finished updating completely.

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

Example:

例子:

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

Here is an example of how to update the state based on previous state:

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

    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>
     }
  }