
Во-первых, да, он асинхронный. Многие разработчики этого не осознают, но setState является асинхронным. Я знаю, что вызовы setState не выглядят асинхронными, и непреднамеренные вызовы могут привести к некоторым ошибкам.
Это хорошая практика (в React она заложена изначально) откладывать согласование для пакетных обновлений. Лучше делать пакетные обновления, если мы знаем, что их будет несколько. Если у вас есть обработчик кликов в браузере, и оба объекта Child и Parent вызывают setState, вы не хотите повторно визуализировать объект Child дважды, а вместо этого предпочитаете пометить их как грязные и повторно обработать вместе, верно? Но что, если setState немедленно обновится до this.state, не дожидаясь окончания согласования? В чем проблема? Что ж, у нас есть несколько причин:
Внутренняя согласованность
Даже если состояние обновляется синхронно, свойства - нет, значит, вы не можете узнать свойства, пока не повторно отрендерите родительский компонент. Объекты, предоставляемые React (состояние, свойства, ссылки), согласованы друг с другом, и если вы введете синхронный setState, вы можете внести некоторые ошибки.
Если вы полагаетесь только на состояние, этот код ниже будет работать:
// initial state value == 0
console.log(this.state.value) // output 0
this.setState({ value: this.state.value + 1 });
console.log(this.state.value) // output 1
this.setState({ value: this.state.value + 1 });
console.log(this.state.value) // 2
Теперь предположим, что это состояние нужно поднять для совместного использования несколькими компонентами, поэтому вы переместите его в родительский элемент следующим образом:
this.props.onIncrement(); // Does the same thing in a parent
Этот код выше просто вызывает метод, переданный из родительского компонента, а в родительском компоненте мы просто вызываем тот же код:
this.setState({ value: this.state.value + 1 });
Чтобы узнать больше о подъеме состояния, прочтите этот пост:
Что ж, после того, как вы изменили свой код, чтобы использовать этот подход, приведенный ниже код больше не будет работать (реквизиты будут обновлены только после повторного рендеринга):
console.log(this.props.value) // output 0 this.props.onIncrement(); console.log(this.props.value) // output 0 this.props.onIncrement(); console.log(this.props.value) // output 0
Таким образом, синхронизация setState не поможет, если другие объекты не будут отражать это обновление до тех пор, пока они не будут повторно отрисованы.
Параллельные обновления
React может назначать разные приоритеты для вызовов setState () в зависимости от того, откуда они исходят, например, обработчик событий, сетевой ответ, анимация и т. Д.
Представьте себе случай, когда вы набираете сообщение, в этом случае вызовы setState () в компоненте TextBox должны быть немедленно сброшены. Однако, если вы получаете новое сообщение во время набора текста, лучше отложить рендеринг, чем допускать прерывание набора текста из-за блокировки цепочки.
Другое дело, если навигация достаточно быстрая, мигание и немедленное скрытие счетчика вызывает ухудшенный UX (пользовательский интерфейс). Представьте, что у вас есть несколько уровней компонентов с разными асинхронными зависимостями, и вы получите каскад счетчиков, мигающих один за другим. Это неприятно как визуально, так и на практике замедляет работу вашего приложения из-за всех перекомпоновок DOM.
Это все, ребята,
Спасибо за прочтение!