** в React 17 автоматический бэтчинг действует внутри React-событий, а в остальных случаях используют unstable_batchedUpdates либо логически объединяют состояние через useReducer, чтобы сократить число ререндеров.
Как в React 17 объединить обновления нескольких стейтов в один ре-рендер?
** в 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 такую группировку нужно выполнять вручную.