{"componentChunkName":"component---src-templates-docs-js","path":"/docs/error-boundaries.html","result":{"data":{"markdownRemark":{"html":"<p>Ранее ошибки JavaScript внутри компонентов портили внутреннее состояние React и заставляли его <a href=\"https://github.com/facebook/react/issues/4026\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">выдавать</a> <a href=\"https://github.com/facebook/react/issues/6895\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">таинственные</a> <a href=\"https://github.com/facebook/react/issues/8579\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">сообщения об ошибках</a> во время следующего рендера. Эти сообщения всегда вызывались ошибками, расположенными где-то выше в коде приложения, но React не предоставлял способа адекватно обрабатывать их в компонентах и не мог обработать их самостоятельно.</p>\n<h2 id=\"introducing-error-boundaries\"><a href=\"#introducing-error-boundaries\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Представляем предохранители (компоненты Error Boundary) </h2>\n<p>Ошибка JavaScript где-то в коде UI не должна прерывать работу всего приложения. Чтобы исправить эту проблему для React-пользователей, React 16 вводит концепцию «предохранителя» (error boundary).</p>\n<p>Предохранители — это компоненты React, которые <strong>отлавливают ошибки JavaScript в любом месте деревьев их дочерних компонентов, сохраняют их в журнале ошибок и выводят запасной UI</strong> вместо рухнувшего дерева компонентов. Предохранители отлавливают ошибки при рендеринге, в методах жизненного цикла и конструкторах деревьев компонентов, расположенных под ними.</p>\n<blockquote>\n<p>Примечание</p>\n<p>Предохранители <strong>не</strong> поймают ошибки в:</p>\n<ul>\n<li>обработчиках событий (<a href=\"#how-about-event-handlers\">подробнее</a>);</li>\n<li>асинхронном коде (например колбэках из <code class=\"gatsby-code-text\">setTimeout</code> или <code class=\"gatsby-code-text\">requestAnimationFrame</code>);</li>\n<li>серверном рендеринге (Server-side rendering);</li>\n<li>самом предохранителе (а не в его дочерних компонентах).</li>\n</ul>\n</blockquote>\n<p>Классовый компонент является предохранителем, если он включает хотя бы один из следующих методов жизненного цикла: <a href=\"/docs/react-component.html#static-getderivedstatefromerror\"><code class=\"gatsby-code-text\">static getDerivedStateFromError()</code></a> или <a href=\"/docs/react-component.html#componentdidcatch\"><code class=\"gatsby-code-text\">componentDidCatch()</code></a>. Используйте <code class=\"gatsby-code-text\">static getDerivedStateFromError()</code> при рендеринге запасного UI в случае отлова ошибки. Используйте <code class=\"gatsby-code-text\">componentDidCatch()</code> при написании кода для журналирования информации об отловленной ошибке.</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">ErrorBoundary</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> hasError<span class=\"token operator\">:</span> <span class=\"token boolean\">false</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">static</span> <span class=\"token function\">getDerivedStateFromError</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">error</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token comment\">// Обновить состояние с тем, чтобы следующий рендер показал запасной UI.</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">{</span> hasError<span class=\"token operator\">:</span> <span class=\"token boolean\">true</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span></span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token function\">componentDidCatch</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">error<span class=\"token punctuation\">,</span> errorInfo</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token comment\">// Можно также сохранить информацию об ошибке в соответствующую службу журнала ошибок</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token function\">logErrorToMyService</span><span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">,</span> errorInfo<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span></span>\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>hasError<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token comment\">// Можно отрендерить запасной UI произвольного вида</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">return</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h1</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Что-то пошло не так.</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h1</span><span class=\"token punctuation\">></span></span><span class=\"token punctuation\">;</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token punctuation\">}</span></span>\n    <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>children<span class=\"token punctuation\">;</span> \n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>И можно дальше им пользоваться, как обыкновенным компонентом:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">ErrorBoundary</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n  </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">MyWidget</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token plain-text\">\n</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token class-name\">ErrorBoundary</span></span><span class=\"token punctuation\">></span></span></code></pre></div>\n<p>Предохранители работают как JavaScript-блоки <code class=\"gatsby-code-text\">catch {}</code>, но только для компонентов. Только классовые компоненты могут выступать в роли предохранителей. На практике чаще всего целесообразным будет один раз описать предохранитель и дальше использовать его по всему приложению.</p>\n<p>Обратите внимание, что <strong>предохранители отлавливают ошибки исключительно в своих дочерних компонентах</strong>. Предохранитель не сможет отловить ошибку внутри самого себя. Если предохранителю не удаётся отрендерить сообщение об ошибке, то ошибка всплывает до ближайшего предохранителя, расположенного над ним в дереве компонентов. Этот аспект их поведения тоже напоминает работу блоков <code class=\"gatsby-code-text\">catch {}</code> в JavaScript.</p>\n<h2 id=\"live-demo\"><a href=\"#live-demo\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Живой пример </h2>\n<p>Посмотрите <a href=\"https://codepen.io/gaearon/pen/wqvxGa?editors=0010\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">пример объявления и использования предохранителя</a> в <a href=\"/blog/2017/09/26/react-v16.0.html\">React 16</a>.</p>\n<h2 id=\"where-to-place-error-boundaries\"><a href=\"#where-to-place-error-boundaries\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Где размещать предохранители </h2>\n<p>Степень охвата кода предохранителями остаётся на ваше усмотрение. Например, вы можете защитить им навигационные (route) компоненты верхнего уровня, чтобы выводить пользователю сообщение «Что-то пошло не так», как это часто делают при обработке ошибок серверные фреймворки. Или вы можете охватить индивидуальными предохранителями отдельные виджеты, чтобы помешать им уронить всё приложение.</p>\n<h2 id=\"new-behavior-for-uncaught-errors\"><a href=\"#new-behavior-for-uncaught-errors\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Новое поведение при обработке неотловленных ошибок </h2>\n<p>Это изменение влечёт за собой существенное последствие. <strong>Начиная с React 16, ошибки, не отловленные ни одним из предохранителей, будут приводить к размонтированию всего дерева компонентов React.</strong></p>\n<p>Хотя принятие этого решения и вызвало споры, судя по нашему опыту, бо́льшим злом будет вывести некорректный UI, чем удалить его целиком. К примеру, в приложении типа Messenger, вывод поломанного UI может привести к тому, что пользователь отправит сообщение не тому адресату. Аналогично, будет хуже, если приложение для проведения платежей выведет пользователю неправильную сумму платежа, чем если оно не выведет вообще ничего.</p>\n<p>Это изменение означает, что при миграции на React 16 вы с большой вероятностью натолкнётесь на незамеченные ранее ошибки в вашем приложении. Добавляя в ваше приложение предохранители, вы обеспечиваете лучший опыт взаимодействия с приложением при возникновении ошибок.</p>\n<p>Например, Facebook Messenger охватывает содержимое боковой и информационной панелей, журнала и поля ввода сообщений отдельными предохранителями. Если один из этих компонентов UI упадёт, то остальные сохранят интерактивность.</p>\n<p>Также мы призываем пользоваться сервисами обработки ошибок JavaScript (или написать собственный аналогичный сервис), чтобы вы знали и могли устранять необработанные исключения в продакшен-режиме.</p>\n<h2 id=\"component-stack-traces\"><a href=\"#component-stack-traces\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Стек вызовов компонентов </h2>\n<p>В режиме разработки React 16 выводит на консоль сообщения обо всех ошибках, возникших при рендеринге, даже если они никак не сказались на работе приложения. Помимо сообщения об ошибке и стека JavaScript, React 16 также выводит и стек вызовов компонентов. Теперь вы в точности можете видеть в каком именно месте дерева компонентов случилось страшное:</p>\n\n  <a class=\"gatsby-resp-image-link\" href=\"/static/f1276837b03821b43358d44c14072945/c3a47/error-boundaries-stack-trace.png\" style=\"display: block\" target=\"_blank\" rel=\"noopener\">\n  \n  <span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block;  max-width: 840px; margin-left: auto; margin-right: auto;\">\n    <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 17.142857142857142%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAIAAAAcOLh5AAAACXBIWXMAABYlAAAWJQFJUiTwAAAAcElEQVQI13WNwQ5FMBQF+/8/ZsECCVW1IOkKaZWtGG2Ut3rJLCb3nJwrzqZBKfqeYaDrkJKqSq71L2pbxvFQyklp69pr7Y0RMQulMDFNrCvzjLU4l/g8yMO2pcu+C4whz8kyioKyjA+XBe9j6Q/Xyw2ql6YYMJsYnwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;\">\n      <img class=\"gatsby-resp-image-image\" style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\" alt=\"&#x41E;&#x448;&#x438;&#x431;&#x43A;&#x430;, &#x43E;&#x442;&#x43B;&#x43E;&#x432;&#x43B;&#x435;&#x43D;&#x43D;&#x430;&#x44F; &#x43F;&#x440;&#x435;&#x434;&#x43E;&#x445;&#x440;&#x430;&#x43D;&#x438;&#x442;&#x435;&#x43B;&#x435;&#x43C;\" title src=\"/static/f1276837b03821b43358d44c14072945/1e088/error-boundaries-stack-trace.png\" srcset=\"/static/f1276837b03821b43358d44c14072945/65ed1/error-boundaries-stack-trace.png 210w,\n/static/f1276837b03821b43358d44c14072945/d10fb/error-boundaries-stack-trace.png 420w,\n/static/f1276837b03821b43358d44c14072945/1e088/error-boundaries-stack-trace.png 840w,\n/static/f1276837b03821b43358d44c14072945/78612/error-boundaries-stack-trace.png 1260w,\n/static/f1276837b03821b43358d44c14072945/c3a47/error-boundaries-stack-trace.png 1601w\" sizes=\"(max-width: 840px) 100vw, 840px\">\n    </span>\n  </span>\n  \n  </a>\n    \n<p>Кроме этого, в стеке вызовов компонентов выводятся имена файлов и номера строк. Такое поведение по умолчанию настроено в проектах, созданных при помощи <a href=\"https://github.com/facebookincubator/create-react-app\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Create React App</a>:</p>\n\n  <a class=\"gatsby-resp-image-link\" href=\"/static/45611d4fdbd152829b28ae2348d6dcba/6dd26/error-boundaries-stack-trace-line-numbers.png\" style=\"display: block\" target=\"_blank\" rel=\"noopener\">\n  \n  <span class=\"gatsby-resp-image-wrapper\" style=\"position: relative; display: block;  max-width: 840px; margin-left: auto; margin-right: auto;\">\n    <span class=\"gatsby-resp-image-background-image\" style=\"padding-bottom: 16.666666666666664%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAADCAIAAAAcOLh5AAAACXBIWXMAABYlAAAWJQFJUiTwAAAAbklEQVQI13WMvQqAMBCD+/7P5SIdRGyP+kM7tGO1P65i5EAUB+Ej5C4h4lAK48jMM6vW6Dr2xoDo/k8ThgHO7USJaOv7bEwJQXC2LNzzHjFiXVErSrnJ+fUp8fmktQqEgLZF00BKnrCWGz+cX70AqbOmQcHKb5YAAAAASUVORK5CYII=&apos;); background-size: cover; display: block;\">\n      <img class=\"gatsby-resp-image-image\" style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\" alt=\"&#x41E;&#x448;&#x438;&#x431;&#x43A;&#x430;, &#x43E;&#x442;&#x43B;&#x43E;&#x432;&#x43B;&#x435;&#x43D;&#x43D;&#x430;&#x44F; &#x43F;&#x440;&#x435;&#x434;&#x43E;&#x445;&#x440;&#x430;&#x43D;&#x438;&#x442;&#x435;&#x43B;&#x435;&#x43C; c &#x43D;&#x43E;&#x43C;&#x435;&#x440;&#x430;&#x43C;&#x438; &#x441;&#x442;&#x440;&#x43E;&#x43A;\" title src=\"/static/45611d4fdbd152829b28ae2348d6dcba/1e088/error-boundaries-stack-trace-line-numbers.png\" srcset=\"/static/45611d4fdbd152829b28ae2348d6dcba/65ed1/error-boundaries-stack-trace-line-numbers.png 210w,\n/static/45611d4fdbd152829b28ae2348d6dcba/d10fb/error-boundaries-stack-trace-line-numbers.png 420w,\n/static/45611d4fdbd152829b28ae2348d6dcba/1e088/error-boundaries-stack-trace-line-numbers.png 840w,\n/static/45611d4fdbd152829b28ae2348d6dcba/78612/error-boundaries-stack-trace-line-numbers.png 1260w,\n/static/45611d4fdbd152829b28ae2348d6dcba/6dd26/error-boundaries-stack-trace-line-numbers.png 1597w\" sizes=\"(max-width: 840px) 100vw, 840px\">\n    </span>\n  </span>\n  \n  </a>\n    \n<p>Если вы не пользуетесь Create React App, вы можете вручную добавить к вашей конфигурации Babel <a href=\"https://www.npmjs.com/package/@babel/plugin-transform-react-jsx-source\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">вот этот плагин</a>. Обратите внимание, что он предназначен исключительно для режима разработки и <strong>должен быть отключён в продакшене</strong>.</p>\n<blockquote>\n<p>Примечание</p>\n<p>Имена компонентов, выводимые в их стеке вызовов, определяются свойством <a href=\"https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/Function/name\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">Function.name</code></a>. Если ваше приложение поддерживает более старые браузеры и устройства, которые могут ещё не предоставлять его нативно (например, IE 11), рассмотрите возможность включения полифилла <code class=\"gatsby-code-text\">Function.name</code> в бандл вашего приложения, например <a href=\"https://github.com/JamesMGreene/Function.name\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">function.name-polyfill</code></a>. В качестве альтернативы, вы можете явным образом задать проп <a href=\"/docs/react-component.html#displayname\"><code class=\"gatsby-code-text\">displayName</code></a> в каждом из ваших компонентов.</p>\n</blockquote>\n<h2 id=\"how-about-trycatch\"><a href=\"#how-about-trycatch\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>А как насчёт try/catch? </h2>\n<p><code class=\"gatsby-code-text\">try</code> / <code class=\"gatsby-code-text\">catch</code> — отличная конструкция, но она работает исключительно в императивном коде:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">showButton</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>В то время, как компоненты React являются декларативными, указывая <em>что</em> должно быть отрендерено:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Button</span></span> <span class=\"token punctuation\">/></span></span></code></pre></div>\n<p>Предохранители сохраняют декларативную природу React и ведут себя так, как вы уже привыкли ожидать от компонентов React. Например, если ошибка, произошедшая в методе <code class=\"gatsby-code-text\">componentDidUpdate</code>, будет вызвана <code class=\"gatsby-code-text\">setState</code> где-то в глубине дерева компонентов, она всё равно корректно всплывёт к ближайшему предохранителю.</p>\n<h2 id=\"how-about-event-handlers\"><a href=\"#how-about-event-handlers\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>А что насчёт обработчиков событий? </h2>\n<p>Предохранители <strong>не</strong> отлавливают ошибки, произошедшие в обработчиках событий.</p>\n<p>React не нуждается в предохранителях, чтобы корректно обработать ошибки в обработчиках событий. В отличие от метода <code class=\"gatsby-code-text\">render</code> и методов жизненного цикла, обработчики событий не выполняются во время рендеринга. Таким образом, даже если они сгенерируют ошибку, React всё равно знает, что нужно выводить на экран.</p>\n<p>Чтобы отловить ошибку в обработчике событий, пользуйтесь обычной JavaScript-конструкцией <code class=\"gatsby-code-text\">try</code> / <code class=\"gatsby-code-text\">catch</code>:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">MyComponent</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">React<span class=\"token punctuation\">.</span>Component</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token function\">constructor</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">super</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state <span class=\"token operator\">=</span> <span class=\"token punctuation\">{</span> error<span class=\"token operator\">:</span> <span class=\"token keyword\">null</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleClick <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">handleClick</span><span class=\"token punctuation\">.</span><span class=\"token function\">bind</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">handleClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">try</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token comment\">// Делаем что-то, что сгенерирует ошибку</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token punctuation\">}</span> <span class=\"token keyword\">catch</span> <span class=\"token punctuation\">(</span>error<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> error <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token punctuation\">}</span></span>  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>error<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">return</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h1</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Отловил ошибку.</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>h1</span><span class=\"token punctuation\">></span></span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token punctuation\">}</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">return</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>button</span> <span class=\"token attr-name\">onClick</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleClick<span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Нажми на меня</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>button</span><span class=\"token punctuation\">></span></span></span>  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Обратите внимание, что приведённый выше пример демонстрирует стандартное поведение JavaScript и не использует предохранителей.</p>\n<h2 id=\"naming-changes-from-react-15\"><a href=\"#naming-changes-from-react-15\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Изменение названия метода по сравнению с React 15 </h2>\n<p>React 15 включал очень ограниченную поддержку предохранителей с другим названием метода: <code class=\"gatsby-code-text\">unstable_handleError</code>. Этот метод больше не работает и вам будет нужно заменить его в вашем коде на <code class=\"gatsby-code-text\">componentDidCatch</code> начиная с первого бета-релиза React 16.</p>\n<p>Для обработки этого изменения мы написали <a href=\"https://github.com/reactjs/react-codemod#error-boundaries\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">codemod</a>, обеспечивающий автоматическую миграцию вашего кода.</p>","frontmatter":{"title":"Предохранители","next":null,"prev":null},"fields":{"path":"content/docs/error-boundaries.md","slug":"docs/error-boundaries.html"}}},"pageContext":{"slug":"docs/error-boundaries.html"}},"staticQueryHashes":[]}