Как в React 17 объединить обновления нескольких стейтов в один ре-рендер?

** в React 17 автоматический бэтчинг действует внутри React-событий, а в остальных случаях используют unstable_batchedUpdates либо логически объединяют состояние через useReducer, чтобы сократить число ререндеров.

Короткий ответ

Что ответить на собеседовании

** в React 17 автоматический бэтчинг действует внутри React-событий, а в остальных случаях используют unstable_batchedUpdates либо логически объединяют состояние через useReducer, чтобы сократить число ререндеров.

Подробный разбор

Ответ с пояснениями

Как в React 17 объединить обновления нескольких стейтов в один ре-рендер?

  • отвечает за асинхронный бэтчинг обновлений
  • в React 17 автоматический бэтчинг выполняется только внутри обработчиков событий React
  • обновления из callback/setTimeout обрабатываются отдельными рендерами
  • для группировки обновлений за пределами React-событий применяют unstable_batchedUpdates из 'react-dom'
  • этот API позволяет вручную объединить несколько setState в один ре-рендер
  • ограничение: API считается нестабильным, поэтому в продакшене его следует использовать осторожно
  • Другой вариант — логически собрать стейты в один объект и управлять им через useReducer

Развёрнутый ответ для собеседования

В React 17 автоматическое объединение (бэтчинг) нескольких обновлений состояния выполняется только внутри синтетических обработчиков событий React. Поэтому все вызовы setState из такого обработчика группируются и приводят к одному ре-рендеру. Если же обновления происходят за пределами этого контекста — например, в setTimeout, Promise или нативном обработчике события, — React 17 по умолчанию запускает отдельный ре-рендер для каждого setState.

Для группировки обновлений в подобных ситуациях React предоставляет низкоуровневую функцию unstable_batchedUpdates из пакета 'react-dom'. С её помощью несколько вызовов setState можно вручную поместить в одну группу, после чего гарантированно выполнить один ре-рендер. Это сокращает число лишних перерисовок. Пример:

import { unstable_batchedUpdates } from 'react-dom';

unstable_batchedUpdates(() => {
setState1(val1);
setState2(val2);
});

Несмотря на нестабильный статус и возможность изменений в будущих версиях, в React 17 этот API считается основным способом оптимизации обновлений вне React-обработчиков.

Если несколько связанных стейтов регулярно требуется изменять одновременно, их также можно объединить в один объект состояния и управлять им через useReducer. Такой подход обеспечивает атомарное обновление и один ре-рендер без дополнительных приёмов.

Итого: в React 17 автоматический бэтчинг действует внутри React-событий, а в остальных случаях используют unstable_batchedUpdates либо логически объединяют состояние через useReducer, чтобы сократить число ререндеров.

Развёрнутый ответ

Основной вариант ответа

В React 17 и более ранних версиях обновления стейта в обработчиках событий выполняются асинхронно, однако по умолчанию каждый setState вызывает отдельный ре-рендер. Для объединения нескольких изменений состояния в один ре-рендер применяют функциональный setState или вручную группируют обновления: автоматический батчинг в основном работает внутри React-событий, но не гарантируется для асинхронных коллбеков.

Основные моменты

  • В React 17 батчинг обновлений выполняется только внутри синхронных обработчиков React. Иными словами, несколько вызовов setState в обработчике одного события объединяются в один ре-рендер.
  • При вызове setState из асинхронного кода — например, из setTimeout, промисов или подписок — батчинг не срабатывает, поэтому каждый setState вызывает отдельный ре-рендер.
  • Чтобы сгруппировать обновления за пределами React-событий, применяют unstable_batchedUpdates из ReactDOM. Эта функция позволяет вручную объединить несколько setState и выполнить один ре-рендер.
  • Ещё один подход — собрать весь связанный стейт в один объект и обновлять его единственным вызовом, заметно уменьшив количество ре-рендеров.

Практический контекст

Распространённый сценарий — обновления поступают из разных источников: событий, таймеров или WebSocket, а количество рендеров необходимо сократить. В React 17 для этого используют ReactDOM.unstable_batchedUpdates либо обновляют объединённое состояние одним вызовом setState, повышая производительность и устраняя лишние перерисовки. Начиная с React 18 автоматический батчинг действует и для асинхронных операций, тогда как в React 17 такую группировку нужно выполнять вручную.

Практика в реальном времени

Подготовьтесь к следующему собеседованию

Interview Boost учитывает вакансию, резюме и технологии и помогает сформулировать ответ прямо во время интервью.

Начать подготовку