правильно использовать метод setState - PullRequest
0 голосов
/ 14 октября 2019

Я новичок в React. В одной из книг мне сказали, что некорректно использовать метод setState в качестве примера ниже:

...
constructor(props) {
   super(props);
   this.state = {
       counter: 0,
          hasButtonBeenClicked: false
   }
}

render() {
 return (
 <button onClick={ this.handleClick }>
    Click
 </button>
 )
}

handleClick = () => {
   this.setState({ counter: this.state.counter + 1 });
   this.setState({ hasButtonBeenClicked: this.state.counter > 0 });
 }
...

, поскольку React выполняет асинхронное изменение данных состояния иЯ могу сгруппировать несколько обновлений для повышения производительности.

Я понял, но поскольку React выполняет изменения асинхронно. могут быть времена и шансы, что первый метод setState будет вызван первым перед вторым методом setState, это просто вопрос вероятности. Но сколько бы раз я ни пытался, второй метод setState всегда вызывается первым, почему?

Ответы [ 4 ]

3 голосов
/ 14 октября 2019

Несмотря на то, что они выполняются асинхронно, маловероятно, что при тестировании с одного и того же браузера и / или на одном и том же оборудовании вы увидите отклонения. Различные браузеры оптимизируют наборы инструкций немного по-разному, что является лучшим выбором для проверки производительности (и почему тестирование во всех основных браузерах для настольных компьютеров по-прежнему рекомендуется, несмотря на то, что коммерческий Chrome часто "достаточно хорош").

Лучший способсделать это - при условии, что вы хотите, чтобы они запускались в определенном порядке - это связать вызов setState следующим образом:

handleClick = () => {
    this.setState({ counter: this.state.counter + 1 }, () => {
        this.setState({ hasButtonBeenClicked: this.state.counter > 0 })
    });
}

Но я бы порекомендовал другой дизайн независимо - связывая логику hasButtonBeenClickedк счетчику собирается ввести проблемы по линии.

1 голос
/ 14 октября 2019
  1. Не ссылка this.state. Используйте вариант обратного вызова setState, чтобы получить текущее состояние оттуда. Это явно защитит вас от ситуаций «изменил состояние, но состояние еще не изменилось».

И 2. Просто поместите эти два обновления в один прогон setState:

this.setState((prevState) => ({
    counter: prevState.counter + 1,
    hasButtonBeenClicked: prevState.counter + 1 > 0 }));
0 голосов
/ 14 октября 2019

Вы правы, React выполняет асинхронное изменение данных состояния для повышения производительности. В вашем случае вы должны написать такой код:

handleClick = () => {
  const counter = this.state.counter + 1;
  this.setState({
    counter: counter,
    hasButtonBeenClicked: counter > 0
  });
}

Или вы можете использовать параметр обратного вызова setState.

0 голосов
/ 14 октября 2019

Если у вас есть много состояний для одновременного обновления, сгруппируйте их все в одно и то же setState:

Вместо:

this.setState({foo: "one"}, () => {
    this.setState({bar: "two"});
});

Просто сделайте это:

this.setState({
    foo: "one",
    bar: "two"
});

Или в вашем случае:

handleClick = () => {
   this.setState({ 
   counter: this.state.counter + 1,
   hasButtonBeenClicked: this.state.counter > 0 
   });
}
...