· ~1 мин чтения · Пантюхов Роман Владимирович
React #185: бесконечный ререндер из-за useSyncExternalStore и как его исправить
Минифицированная ошибка React #185 расшифровывается как «Maximum update depth exceeded»: компонент бесконечно перерисовывается, и React в какой-то момент прерывает работу. Страница при этом падает целиком. Я встретил её на собственном сайте, когда выносил состояние (тему оформления, выбор cookie, значения из localStorage) в отдельное внешнее хранилище.
Как работает useSyncExternalStore
Хук принимает функцию подписки и функцию getSnapshot, которая возвращает текущее значение. React вызывает getSnapshot часто и сравнивает результаты между вызовами через Object.is. Если два подряд идущих вызова вернули разные значения, React решает, что хранилище изменилось, и запускает новую отрисовку.
Где возникает ловушка
Если getSnapshot каждый раз строит новый объект или массив — например, разбирает JSON из localStorage и возвращает свежий {...} — то два вызова подряд вернут разные ссылки, даже когда данные одинаковы. React видит «изменение», перерисовывается, снова вызывает функцию, снова получает новую ссылку — и так до тех пор, пока не сработает защита от бесконечного цикла.
Как это исправить
Снимок должен быть стабильным: пока данные не изменились, функция возвращает ровно то же значение. Самое надёжное — хранить в снимке примитив, например строку, а разбирать её уже в компоненте. Так я сделал для согласия на cookie: в localStorage лежит строка, getSnapshot возвращает эту строку, и сравнение Object.is работает как надо. Если нужен объект, кэшируйте его и пересоздавайте только при реальном изменении данных. Отдельно задайте getServerSnapshot, чтобы сервер и первая отрисовка в браузере совпадали.
Урок: не списывайте ошибку на тесты
Сначала я принял эту ошибку за артефакт прокрутки в автотестах и потерял время. Любую ошибку #185 нужно считать настоящей, пока не доказано обратное: она означает реальный цикл отрисовки, который у пользователя может проявиться на слабом устройстве. Если при разработке сайта вам нужна такая внимательность к деталям, это часть разработки сайтов под ключ.