Что означает ошибка too many renders в React и как её исправить
Что проверяют
Понимаете ли вы разницу между рендером и эффектом и читаете ли сообщение React буквально. Ошибка говорит не о медленном интерфейсе, а о зацикливании: рендер сам запланировал следующий рендер. По ответу видно, усвоил ли кандидат, что менять состояние во время рендера нельзя.
Как отвечать
React ограничивает число повторных рендеров подряд, чтобы вместо зависшей вкладки разработчик получил внятную ошибку. Значит где-то обновление состояния запускается на каждом рендере. Две основные причины:
- сеттер вызван прямо в разметке, обычно из-за потерянной стрелки:
<button onClick={setOpen(true)}> // вызов при рендере
<button onClick={() => setOpen(true)}> // правильно- эффект безусловно меняет состояние, от которого сам же зависит:
useEffect(() => setCount(count + 1), [count]);Порядок разбора такой: найти компонент в трассировке, проверить, не зовётся ли сеттер без обёртки прямо в теле, затем посмотреть эффекты и их зависимости. Лечится обёрткой обработчика в функцию, условием выхода в эффекте, а чаще всего тем, что значение, выводимое из пропсов и состояния, вообще не кладут в состояние, а считают при рендере.
Где спотыкаются
Убирают массив зависимостей целиком, чтобы «эффект не перезапускался». Эффект без второго аргумента выполняется после каждого рендера, то есть цикл остаётся на месте, а подсказка линтера про зависимости пропадает.
Верят, что функциональная форма лечит сама по себе. Вызов setCount(c => c + 1) с зависимостью [count] крутится ровно так же. Помогает не форма, а то, что после неё count можно честно убрать из зависимостей.
Не замечают нестабильную ссылку: объект или массив, созданный в теле компонента, на каждом рендере новый, поэтому эффект с ним в зависимостях срабатывает всегда. Если внутри есть обновление состояния, получается тот же цикл, лечится это useMemo или выносом значения за пределы компонента.