React: ошибка "Maximum update depth exceeded"

Ошибка "Maximum update depth exceeded" в React возникает, когда компонент застревает в бесконечном цикле обновлений. Чаще всего это происходит при вызове setState
внутри useEffect
без корректных условий завершения. Разберём причины возникновения ошибки и способы её исправления.
Почему возникает ошибка "Maximum update depth exceeded"
Эта ошибка обычно возникает, когда setState
вызывается в useEffect
без корректной настройки обновлений. Например, если состояние обновляется при каждом рендере без чёткого условия завершения, компонент застревает в цикле, бесконечно перезапуская эффект. Это приводит к превышению допустимой глубины обновлений.
Пример возникновения ошибки
Рассмотрим пример, где setState
вызывается в useEffect
без условий завершения:
import React, { useState, useEffect } from 'react';
function ExampleComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
setCount(count + 1);
});
return <div>Count: {count}</div>;
}
export default ExampleComponent;
В этом примере setCount
вызывается каждый раз, когда компонент рендерится, из-за чего useEffect
продолжает выполняться бесконечно. Это приводит к ошибке "Maximum update depth exceeded".
Исправление ошибки: использование колбэка в setState
Часто для корректного обновления состояния на основе предыдущего значения лучше использовать колбэк внутри setState
. Это позволяет предотвратить лишние рендеры и решить проблему бесконечного цикла:
import React, { useState, useEffect } from 'react';
function ExampleComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
setCount(prevCount => prevCount + 1);
}, []);
return <div>Count: {count}</div>;
}
export default ExampleComponent;
Теперь useEffect
выполнится один раз при монтировании компонента, что предотвратит бесконечный цикл и обеспечит корректное поведение.
Использование условий для предотвращения бесконечного цикла
В некоторых случаях можно добавить условия внутри useEffect
, чтобы контролировать выполнение setState
и предотвратить бесконечный цикл:
import React, { useState, useEffect } from 'react';
function ExampleComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
if (count < 5) {
setCount(count + 1);
}
}, [count]);
return <div>Count: {count}</div>;
}
export default ExampleComponent;
Здесь setCount
срабатывает только при count < 5
, что ограничивает количество обновлений и предотвращает бесконечный цикл.
Советы по предотвращению ошибки "Maximum update depth exceeded"
- Избегайте обновлений состояния в
useEffect
без условий: Убедитесь, что обновление состояния имеет чёткое условие завершения. - Используйте колбэк в
setState
: Если состояние должно зависеть от предыдущего значения, колбэк-версияsetState
поможет избежать ненужных рендеров. - Ограничивайте обновления: В сложных компонентах с большим количеством состояний устанавливайте ограничения для обновлений, чтобы избежать бесконечного цикла.
Дополнительные ресурсы и курсы
Если вас интересует React, ознакомьтесь с решением доволно нередкой проблемы "TypeError: Cannot destructure property 'children' of 'undefined".