React 16.0 представил Границы ошибок.
Границы ошибок - это компоненты React, которые перехватывают ошибки JavaScript в любом месте своего дочернего дерева компонентов, регистрируют эти ошибки и отображают резервный пользовательский интерфейс вместо дерева компонентов, в котором произошел сбой.
Возьмем этот пример:
Если мы запустим этот код, ErrorBoundary
перехватит ошибку, отобразит резервный пользовательский интерфейс (Something went wrong
) и запишет ошибку в консоль.
Границы ошибок - хороший способ централизовать обработку ошибок в приложениях React, но они могут отлавливать только определенные ошибки:
Границы ошибок не обнаруживают ошибки для:
* Обработчики событий
* Асинхронный код (например,
setTimeout
илиrequestAnimationFrame
обратные вызовы)
* Рендеринг на стороне сервера
* Ошибки, возникающие в самой границе ошибки (а не в ее дочерних элементах)
Большинство приложений извлекают данные асинхронно, поэтому, если наш BrokenComponent
это сделает, наш ErrorBoundary
не поймает ошибку и ничего не будет отображаться. Мы заметим ошибку, потому что браузер выдаст ошибку в консоли (Uncaught (in promise)
в Chrome).
Обычный способ исправить это - заставить наш компонент обрабатывать свои собственные ошибки.
Но это такое разочарование. Мы не можем использовать наши границы ошибок для управления всеми ошибками одинаковым образом, что может привести к дублированию.
Проблема в том, что асинхронный код выполняется вне фаз рендеринга и фиксации React. Как же тогда это исправить? Решение прямо перед нами. К счастью, Дан Абрамов всегда готов открыть нам глаза:
Просто используйте setState
. Бросьте внутрь обратного вызова. Посмотрите, как ошибки обнаруживаются вашими границами ошибок.
Давайте извлечем этот фрагмент для многоразового крючка:
И используйте это в нашем коде:
Вот и все. Теперь наш ErrorBoundary
может обрабатывать все ошибки, как синхронные, так и асинхронные.
Расставания и совместное будущее
Предлагаемое решение простое, но, честно говоря, кажется немного хакерским. Мы заставляем асинхронную ошибку на этапе рендеринга React с помощью молотка (плохой setState
). Нам это не совсем удобно, но мы пока не нашли другого варианта. Так что, если у кого-то есть лучшее решение, мы все - уши 😃.
В любом случае, в эти дни я сплю крепче после того, как окунулся в новый параллельный режим React. Мы будем писать следующий код, который соответствует этому шаблону обработки всех ошибок с помощью границ ошибок:
Все это все еще экспериментально, но кажется, что окончательная версия будет очень похожей (если не такой). Хорошо иметь наш код, пригодный для будущего.