Почему при изменении состояния компонента происходит ререндер, а не размонтирование и монтирование
Что проверяют
Понимаете ли вы, чем идентичность компонента отличается от его содержимого. React решает, оставлять ли экземпляр, по позиции в дереве, типу элемента и key, а не по тому, что вы вернули из функции. Из этого же знания растёт умение осознанно сбрасывать состояние.
Как отвечать
Рендер это вызов функции компонента, который возвращает описание интерфейса. React сравнивает новое описание со старым в том же месте дерева. Совпали тип и key, значит прежний фибер живёт дальше: состояние хуков, рефы, узел DOM, позиция скролла и фокус сохраняются, а в DOM уезжают только изменившиеся атрибуты. Не совпали, значит старое поддерево размонтируется с чисткой эффектов, а новое монтируется с нуля.
Ключевая мысль: состояние хранится не в DOM и не в замыкании, а в фибере, привязанном к позиции. Размонтирование на каждый setState означало бы потерю локального состояния, повторный прогон эффектов с пустым списком зависимостей, сброс незакоммиченного ввода и разрыв переходов CSS. То есть дело не только в скорости, а в семантике: обновление данных не означает, что перед пользователем другой элемент.
Отсюда управляемый приём. Чтобы сбросить состояние намеренно, меняют key: запись вида <Form key={userId} /> честно пересоздаст форму при смене пользователя, вместо того чтобы вычищать поля эффектом.
Полезное дополнение: рендер не равен изменению DOM. Если различий нет, коммита тоже не будет, а setState с тем же значением по сравнению Object.is прервёт обновление ещё раньше.
Где спотыкаются
Объявляют компонент внутри тела другого компонента. На каждый рендер получается новая функция, то есть новый тип, то есть полное размонтирование поддерева. Классический симптом: поле ввода теряет фокус после каждой буквы.
Ставят key={Math.random()} и пересоздают всё на каждом рендере. Обратная крайность это индекс массива в роли ключа: при вставке в середину React оставит прежние экземпляры на прежних позициях, и состояние прилипнет не к тем элементам.
Путают ререндер с перерисовкой страницы и обмазывают memo всё подряд. Повторный вызов функции обычно дешёвый, а дорогими оказываются работа в эффектах и лишние запросы, которые memo не лечит.