React 16.0 представил Границы ошибок.

Границы ошибок - это компоненты React, которые перехватывают ошибки JavaScript в любом месте своего дочернего дерева компонентов, регистрируют эти ошибки и отображают резервный пользовательский интерфейс вместо дерева компонентов, в котором произошел сбой.

Возьмем этот пример:

Если мы запустим этот код, ErrorBoundary перехватит ошибку, отобразит резервный пользовательский интерфейс (Something went wrong) и запишет ошибку в консоль.

Границы ошибок - хороший способ централизовать обработку ошибок в приложениях React, но они могут отлавливать только определенные ошибки:

Границы ошибок не обнаруживают ошибки для:

* Обработчики событий

* Асинхронный код (например, setTimeout или requestAnimationFrame обратные вызовы)

* Рендеринг на стороне сервера

* Ошибки, возникающие в самой границе ошибки (а не в ее дочерних элементах)

Большинство приложений извлекают данные асинхронно, поэтому, если наш BrokenComponent это сделает, наш ErrorBoundary не поймает ошибку и ничего не будет отображаться. Мы заметим ошибку, потому что браузер выдаст ошибку в консоли (Uncaught (in promise) в Chrome).

Обычный способ исправить это - заставить наш компонент обрабатывать свои собственные ошибки.

Но это такое разочарование. Мы не можем использовать наши границы ошибок для управления всеми ошибками одинаковым образом, что может привести к дублированию.

Проблема в том, что асинхронный код выполняется вне фаз рендеринга и фиксации React. Как же тогда это исправить? Решение прямо перед нами. К счастью, Дан Абрамов всегда готов открыть нам глаза:

Просто используйте setState. Бросьте внутрь обратного вызова. Посмотрите, как ошибки обнаруживаются вашими границами ошибок.

Давайте извлечем этот фрагмент для многоразового крючка:

И используйте это в нашем коде:

Вот и все. Теперь наш ErrorBoundary может обрабатывать все ошибки, как синхронные, так и асинхронные.

Расставания и совместное будущее

Предлагаемое решение простое, но, честно говоря, кажется немного хакерским. Мы заставляем асинхронную ошибку на этапе рендеринга React с помощью молотка (плохой setState). Нам это не совсем удобно, но мы пока не нашли другого варианта. Так что, если у кого-то есть лучшее решение, мы все - уши 😃.

В любом случае, в эти дни я сплю крепче после того, как окунулся в новый параллельный режим React. Мы будем писать следующий код, который соответствует этому шаблону обработки всех ошибок с помощью границ ошибок:

Все это все еще экспериментально, но кажется, что окончательная версия будет очень похожей (если не такой). Хорошо иметь наш код, пригодный для будущего.