Подтвердить что ты не робот

Что происходит при использовании this.setState несколько раз в компоненте React?

Я хотел проверить, что происходит, когда вы используете 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')
);

Как вы увидите, на каждом рендере появляется предупреждение о том, что "render" появляется.

Есть ли у вас объяснение, почему он работал правильно?

4b9b3361

Ответ 1

Реагировать пакеты обновлений состояния, которые происходят в обработчиках событий и методах жизненного цикла. Таким образом, если вы обновляете состояние несколько раз в обработчике <div onClick />, React будет ожидать завершения обработки событий перед повторным рендерингом.

Чтобы быть ясным, это работает только в обработчиках синтетических событий, управляемых с помощью реакций и методах жизненного цикла. Например, обновления состояния не обрабатываются в обработчиках событий AJAX и setTimeout.

Ответ 2

Метод setState() не сразу обновляет состояние компонента, а просто переносит обновление в очередь для последующей обработки. React может объединить несколько запросов обновления, чтобы сделать рендеринг более эффективным. В связи с этим необходимо предпринять особые меры предосторожности при попытке обновления состояния на основе предыдущего состояния компонента.

Например, следующий код только увеличит атрибут значения состояния на 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, [callback]) может принимать функцию обновления в качестве первого аргумента для обновления состояния на основе предыдущего состояния и свойств. Возвращаемое значение функции обновления будет слабо слито с предыдущим состоянием компонента. Метод обновляет состояние асинхронно, поэтому существует обратный вызов опции, который будет вызываться после завершения состояния полностью.

Пример:

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