Render и commit, снимки состояния, batching, идентичность дерева, StrictMode, reconciliation и конкурентный рендеринг.
Отладка React становится предсказуемой, когда render воспринимается как вычисление снимка, а не как последовательное редактирование экрана.
Вы сможете объяснить повторный render, сохранение и сброс state, stale closures, batching и причины, по которым React может прервать вычисление.
До начала достаточно чистые функции-компоненты, props, state и ссылочную идентичность объектов. В конце должен появиться не конспект, а интерактивное дерево с управляемой identity, трассировкой render/commit и регрессионными тестами перестановок.
Обновление ставит работу в очередь. В render phase React вызывает компоненты и вычисляет следующее дерево; в commit phase применяет необходимый минимум изменений к host-среде. Только committed tree становится видимым. Поэтому измерять DOM или выполнять внешний эффект во время render нельзя: вычисление может повториться или не попасть в commit.
Рабочая проверка. Разделите журнал на записи render и callback ref/Effect после commit, затем сравните последовательность.
Типичная поломка. Считать каждый вызов компонента гарантированной перерисовкой DOM.
Вызов setter не меняет локальную переменную текущего render. Он запрашивает новый render с другим снимком. Обработчик, созданный в старом render, продолжает видеть старые props и state. Это объясняет лог сразу после setCount и delayed callbacks; для серии обновлений от предыдущего значения нужен functional updater.
Следующий фрагмент показывает минимальный рабочий контракт, а не заготовку для слепого копирования.
function addThree() {
setCount(value => value + 1);
setCount(value => value + 1);
setCount(value => value + 1);
}Каждая updater-функция получает результат предыдущей queued updater, поэтому итог увеличивается на три.
Рабочая проверка. Сравните три вызова setCount(count + 1) с тремя functional updaters.
Типичная поломка. Ожидать, что count изменится между setter-вызовами текущего handler.
React группирует queued state updates и выполняет render после завершения обработчика. Это предотвращает промежуточные полусостояния и лишние commits. Batching не означает слияние объектов или немедленное изменение переменных. flushSync существует для редких интеграций, когда сторонний API требует уже обновлённый DOM, и ухудшает производительность при ритуальном применении.
Рабочая проверка. Подсчитайте commits для нескольких setter-вызовов в одном событии и проверьте итоговое состояние.
Типичная поломка. Вызывать flushSync после каждого setter ради привычной последовательности.
State хранится у React, а связывается с позицией компонента в дереве. Совпадающие type и key в той же позиции сохраняют экземпляр; изменение type или key сбрасывает subtree. Вложенное объявление компонента создаёт новую function identity на каждом render и может непреднамеренно сбрасывать state.
Рабочая проверка. Переключите две карточки одного типа с разными key и зафиксируйте намеренный reset формы.
Типичная поломка. Объявлять компонент строки внутри родительского компонента.
React сопоставляет предыдущих и следующих siblings по type и key, затем обновляет изменившиеся host props. Это эвристика публичной модели, а детали Fiber не являются контрактом приложения. Нельзя опираться на конкретное число внутренних узлов или порядок обхода. Оптимизация должна сохранять видимое поведение независимо от стратегии сопоставления.
Рабочая проверка. Поменяйте тип корневого элемента subtree и наблюдайте размонтирование его state.
Типичная поломка. Использовать случайный key как способ «обновить» компонент при любой проблеме.
В development StrictMode дополнительно вызывает render-функции, Effect setup/cleanup и ref callbacks, чтобы проявить нечистоту и отсутствующую очистку. Это не production-дублирование пользовательского действия. Исправление — сделать render чистым и Effect симметричным, а не выключать проверку.
Рабочая проверка. Добавьте подписку с корректным cleanup и убедитесь, что после setup-cleanup-setup остаётся один listener.
Типичная поломка. Ставить module flag didRun, скрывая утечку Effect в StrictMode.
Concurrent rendering означает, что React может приостановить, продолжить или отбросить render work, сохраняя commit согласованным. Это не параллельное выполнение компонента в worker и не гонка DOM-записей. Transitions отмечают несрочное обновление; ввод остаётся срочным, а тяжёлое обновление результатов может быть interruptible.
Рабочая проверка. Разделите input state и transition обновления большого списка, затем проверьте отзывчивость ввода.
Типичная поломка. Обернуть controlled input setter в transition и получить задерживающееся поле.
Инструментирование не должно становиться причиной новых renders или менять identity props. Счётчики render полезны только вместе с commit и причиной обновления. React DevTools Profiler показывает commits и затраты; обычный console.log внутри render показывает вызовы, включая отброшенные. Для пользовательской задержки важны browser performance marks и Web Vitals.
Рабочая проверка. Сопоставьте логи render с Profiler commits для transition, которое было прервано новым вводом.
Типичная поломка. Делать вывод о производительности по числу console.log без времени и commit.
Исправьте форму редактирования каталога: сейчас state переезжает между строками, updater теряет быстрые изменения, render пишет во внешнее хранилище, а StrictMode удваивает видимый эффект. Добавьте трассировку phases без изменения семантики.
Критерий завершения: каждый наблюдаемый эффект относится к handler или commit, состояние связано с доменной identity, а серия обновлений даёт детерминированный результат. Сначала зафиксируйте наблюдаемое поведение тестом или измерением, затем меняйте реализацию.
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.
Далее: События и локальное состояние