{"componentChunkName":"component---src-templates-docs-js","path":"/docs/hooks-effect.html","result":{"data":{"markdownRemark":{"html":"<p><em>Хуки</em> — нововведение в React 16.8, которое позволяет использовать состояние и другие возможности React без написания классов.</p>\n<p><em>Хук эффекта</em> даёт вам возможность выполнять побочные эффекты в функциональном компоненте:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">import</span> React<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> useState<span class=\"token punctuation\">,</span> useEffect <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span><span class=\"token punctuation\">;</span></span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">Example</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>count<span class=\"token punctuation\">,</span> setCount<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token comment\">// Аналогично componentDidMount и componentDidUpdate:</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token function\">useEffect</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token comment\">// Обновляем заголовок документа с помощью API браузера</span></span><span class=\"gatsby-highlight-code-line\">    document<span class=\"token punctuation\">.</span>title <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Вы нажали </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>count<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> раз</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<span class=\"token plain-text\">      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Вы нажали </span><span class=\"token punctuation\">{</span>count<span class=\"token punctuation\">}</span><span class=\"token plain-text\"> раз</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<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 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 punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">setCount</span><span class=\"token punctuation\">(</span>count <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<span class=\"token plain-text\">        Нажми на меня</span>\n<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 class=\"token plain-text\"></span>\n<span class=\"token plain-text\">    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Этот фрагмент основан на <a href=\"/docs/hooks-state.html\">примере со счётчиком из предыдущей страницы</a>, только мы добавили новую функциональность: мы изменяем заголовок документа на пользовательское сообщение, которое также содержит количество нажатий кнопки.</p>\n<p>Побочными эффектами в React-компонентах могут быть: загрузка данных, оформление подписки и изменение DOM вручную. Неважно, называете ли вы эти операции «побочными эффектам» (или просто «эффектами») или нет, скорее всего вам доводилось ранее использовать их в своих компонентах.</p>\n<blockquote>\n<p>Совет</p>\n<p>Если вам знакомы классовые методы жизненного цикла React, хук <code class=\"gatsby-code-text\">useEffect</code> представляет собой совокупность методов <code class=\"gatsby-code-text\">componentDidMount</code>, <code class=\"gatsby-code-text\">componentDidUpdate</code>, и <code class=\"gatsby-code-text\">componentWillUnmount</code>.</p>\n</blockquote>\n<p>Существует два распространённых вида побочных эффектов в компонентах React: компоненты, которые требуют и не требуют сброса. Давайте рассмотрим оба примера более детально.</p>\n<h2 id=\"effects-without-cleanup\"><a href=\"#effects-without-cleanup\" 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 обновил DOM.</strong> Сетевые запросы, изменения DOM вручную, логирование — всё это примеры эффектов, которые не требуют сброса. После того, как мы запустили их, можно сразу забыть о них, ведь больше никаких дополнительных действий не требуется. Давайте сравним, как классы и хуки позволяют нам реализовывать побочные эффекты.</p>\n<h3 id=\"example-using-classes\"><a href=\"#example-using-classes\" 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>Пример с использованием классов </h3>\n<p>В классовых React-компонентах метод <code class=\"gatsby-code-text\">render</code> сам по себе не должен вызывать никаких побочных эффектов. Он не подходит для этих целей, так как в основном мы хотим выполнить наши эффекты <em>после</em> того, как React обновил DOM.</p>\n<p>Вот почему в классах React мы размещаем побочные эффекты внутрь <code class=\"gatsby-code-text\">componentDidMount</code> и <code class=\"gatsby-code-text\">componentDidUpdate</code>. Возвращаясь к нашему примеру, здесь представлен счётчик, реализованный с помощью классового React-компонента. Он обновляет заголовок документа сразу же после того, как React вносит изменения в DOM:</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\">Example</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>\n      count<span class=\"token operator\">:</span> <span class=\"token number\">0</span>\n    <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 function\">componentDidMount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    document<span class=\"token punctuation\">.</span>title <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Вы нажали </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>count<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> раз</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span></span><span class=\"gatsby-highlight-code-line\"></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token function\">componentDidUpdate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    document<span class=\"token punctuation\">.</span>title <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Вы нажали </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>count<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> раз</span><span class=\"token template-punctuation string\">`</span></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=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<span class=\"token plain-text\">        </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Вы нажали </span><span class=\"token punctuation\">{</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>count<span class=\"token punctuation\">}</span><span class=\"token plain-text\"> раз</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<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 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 punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <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> count<span class=\"token operator\">:</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>count <span class=\"token operator\">+</span> <span class=\"token number\">1</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<span class=\"token plain-text\">          Нажми на меня</span>\n<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 class=\"token plain-text\"></span>\n<span class=\"token plain-text\">      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span>\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Обратите внимание, что <strong>нам приходится дублировать наш код между этими классовыми методами жизненного цикла.</strong></p>\n<p>Это всё потому, что во многих случаях, мы хотим выполнять одни и те же побочные эффекты вне зависимости от того, был ли компонент только что смонтирован или обновлён. Мы хотим чтобы они выполнялись после каждого рендера — но у классовых React-компонентов нет таких встроенных методов. Мы могли бы вынести этот метод отдельно, но нам бы всё равно пришлось бы вызывать его в двух местах.</p>\n<p>А сейчас, давайте рассмотрим, как мы можем сделать то же самое с использованием хука <code class=\"gatsby-code-text\">useEffect</code>.</p>\n<h3 id=\"example-using-hooks\"><a href=\"#example-using-hooks\" 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>Пример с использованием хуков </h3>\n<p>Мы уже рассматривали этот пример немного ранее, но давайте разберём его более подробно:</p>\n<div class=\"gatsby-highlight has-highlighted-lines\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">import</span> React<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> useState<span class=\"token punctuation\">,</span> useEffect <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span><span class=\"token punctuation\">;</span></span>\n<span class=\"token keyword\">function</span> <span class=\"token function\">Example</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>count<span class=\"token punctuation\">,</span> setCount<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token function\">useEffect</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    document<span class=\"token punctuation\">.</span>title <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Вы нажали </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>count<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> раз</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>div</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<span class=\"token plain-text\">      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Вы нажали </span><span class=\"token punctuation\">{</span>count<span class=\"token punctuation\">}</span><span class=\"token plain-text\"> раз</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>p</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<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 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 punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token function\">setCount</span><span class=\"token punctuation\">(</span>count <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<span class=\"token plain-text\">        Нажми на меня</span>\n<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 class=\"token plain-text\"></span>\n<span class=\"token plain-text\">    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span>div</span><span class=\"token punctuation\">></span></span>\n  <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p><strong>Что же делает <code class=\"gatsby-code-text\">useEffect</code>?</strong> Используя этот хук, вы говорите React сделать что-то после рендера. React запомнит функцию (то есть «эффект»), которую вы передали и вызовет её после того, как внесёт все изменения в DOM. В этом эффекте мы устанавливаем заголовок документа, но мы также можем выполнить запрос данных или вызвать какой-нибудь императивный API.</p>\n<p><strong>Почему же мы вызываем <code class=\"gatsby-code-text\">useEffect</code> непосредственно внутри компонента?</strong> Это даёт нам доступ к переменной состояния <code class=\"gatsby-code-text\">count</code> (или любым другим пропсам) прямиком из эффекта. Нам не нужен специальный API для доступа к этой переменной — она уже находится у нас в области видимости функции. Хуки используют JavaScript-замыкания, и таким образом, им не нужен специальный API для React, поскольку сам JavaScript уже имеет готовое решение для этой задачи.</p>\n<p><strong>Выполняется ли <code class=\"gatsby-code-text\">useEffect</code> после каждого рендера?</strong> Разумеется! По умолчанию он будет выполняться после каждого рендера и обновления. Мы рассмотрим, <a href=\"#tip-optimizing-performance-by-skipping-effects\">как настраивать это</a> немного позже. Вместо того, чтобы воспринимать это с позиции «монтирования» и «обновления», мы советуем просто иметь в виду, что эффекты выполняются после каждого рендера. React гарантирует, что он запустит эффект только после того, как DOM уже обновился.</p>\n<h3 id=\"detailed-explanation\"><a href=\"#detailed-explanation\" 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>Подробное объяснение </h3>\n<p>Мы узнали немного больше о принципе работы эффектов и теперь этот код уже вовсе не кажется таким непонятным:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">Example</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>count<span class=\"token punctuation\">,</span> setCount<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token function\">useEffect</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    document<span class=\"token punctuation\">.</span>title <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Вы нажали </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>count<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> раз</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Мы объявляем переменную состояния <code class=\"gatsby-code-text\">count</code> и говорим React, что мы хотим использовать эффект. Далее, мы передаём функцию в хук <code class=\"gatsby-code-text\">useEffect</code>. Эта функция как раз и <em>будет</em> нашим эффектом. Внутри этого эффекта мы устанавливаем заголовок документа, используя API браузера <code class=\"gatsby-code-text\">document.title</code>. Мы можем получать доступ к актуальной переменной <code class=\"gatsby-code-text\">count</code> изнутри эффекта, так как он находится в области видимости нашей функции. Когда React рендерит наш компонент, он запоминает эффект, который мы использовали, и запускает его после того, как обновит DOM. Это будет происходить при каждом рендере, в том числе и при первоначальном.</p>\n<p>Опытные JavaScript-разработчики могут подметить, что функция, которую мы передаём в <code class=\"gatsby-code-text\">useEffect</code>, будет меняться при каждом рендере. На самом деле, это было сделано преднамеренно. Это как раз то, что даёт нам возможность получать актуальную версию переменной <code class=\"gatsby-code-text\">count</code> изнутри эффекта, не беспокоясь о том, что её значение устареет. Каждый раз при повторном рендере, мы ставим в очередь <em>новый</em> эффект, который заменяет предыдущий. В каком-то смысле, это включает поведение эффектов как часть результата рендера, то есть каждый эффект «принадлежит» определённому рендеру. Мы расскажем о преимуществах данного подхода <a href=\"#explanation-why-effects-run-on-each-update\">далее на этой странице</a>.</p>\n<blockquote>\n<p>Совет</p>\n<p>В отличие от <code class=\"gatsby-code-text\">componentDidMount</code> или <code class=\"gatsby-code-text\">componentDidUpdate</code>, эффекты, запланированные с помощью <code class=\"gatsby-code-text\">useEffect</code>, не блокируют браузер при попытке обновить экран. Ваше приложение будет быстрее реагировать на действия пользователя, даже когда эффект ещё не закончился. Большинству эффектов не нужно работать в синхронном режиме. Есть редкие случаи, когда им всё же нужно это делать (например, измерять раскладку), но для этого мы разработали специальный хук <a href=\"/docs/hooks-reference.html#uselayouteffect\"><code class=\"gatsby-code-text\">useLayoutEffect</code></a> с точно таким же API, как и у <code class=\"gatsby-code-text\">useEffect</code>.</p>\n</blockquote>\n<h2 id=\"effects-with-cleanup\"><a href=\"#effects-with-cleanup\" 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<h3 id=\"example-using-classes-1\"><a href=\"#example-using-classes-1\" 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>Пример с использованием классов </h3>\n<p>В React-классе, вы, как правило, оформили бы подписку в <code class=\"gatsby-code-text\">componentDidMount</code> и отменили бы её в <code class=\"gatsby-code-text\">componentWillUnmount</code>. Например, предположим, что у нас есть некий модуль <code class=\"gatsby-code-text\">ChatAPI</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\">FriendStatus</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> isOnline<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>handleStatusChange <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">handleStatusChange</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=\"gatsby-highlight-code-line\">  <span class=\"token function\">componentDidMount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">subscribeToFriendStatus</span><span class=\"token punctuation\">(</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleStatusChange</span><span class=\"gatsby-highlight-code-line\">    <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=\"gatsby-highlight-code-line\"></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token function\">componentWillUnmount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">unsubscribeFromFriendStatus</span><span class=\"token punctuation\">(</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleStatusChange</span><span class=\"gatsby-highlight-code-line\">    <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=\"gatsby-highlight-code-line\"></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token function\">handleStatusChange</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">status</span><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></span><span class=\"gatsby-highlight-code-line\">      isOnline<span class=\"token operator\">:</span> status<span class=\"token punctuation\">.</span>isOnline</span><span class=\"gatsby-highlight-code-line\">    <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>\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=\"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>isOnline <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\">return</span> <span class=\"token string\">'Загрузка...'</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">return</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>isOnline <span class=\"token operator\">?</span> <span class=\"token string\">'В сети'</span> <span class=\"token operator\">:</span> <span class=\"token string\">'Не в сети'</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Обратите внимание, что <code class=\"gatsby-code-text\">componentDidMount</code> и <code class=\"gatsby-code-text\">componentWillUnmount</code> по сути содержат идентичный код. Методы жизненного цикла вынуждают нас разбивать эту логику, хоть и фактически код обоих методов относится к одному и тому же эффекту.</p>\n<blockquote>\n<p>Примечание</p>\n<p>Вы могли заметить, что для правильной работы, нашему компоненту также нужен <code class=\"gatsby-code-text\">componentDidUpdate</code>. Мы вернёмся к этому моменту <a href=\"#explanation-why-effects-run-on-each-update\">ниже на этой странице</a>.</p>\n</blockquote>\n<h3 id=\"example-using-hooks-1\"><a href=\"#example-using-hooks-1\" 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>Пример с использованием хуков </h3>\n<p>Давайте рассмотрим, как этот компонент будет выглядеть, если написать его с помощью хуков.</p>\n<p>Вы должно быть подумали, что нам потребуется отдельный эффект для выполнения сброса. Так как код для оформления и отмены подписки тесно связан с <code class=\"gatsby-code-text\">useEffect</code>, мы решили объединить их. Если ваш эффект возвращает функцию, React выполнит её только тогда, когда наступит время сбросить эффект.</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\">import</span> React<span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span> useState<span class=\"token punctuation\">,</span> useEffect <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">FriendStatus</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\">const</span> <span class=\"token punctuation\">[</span>isOnline<span class=\"token punctuation\">,</span> setIsOnline<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token function\">useEffect</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">function</span> <span class=\"token function\">handleStatusChange</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">status</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token function\">setIsOnline</span><span class=\"token punctuation\">(</span>status<span class=\"token punctuation\">.</span>isOnline<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=\"gatsby-highlight-code-line\"></span><span class=\"gatsby-highlight-code-line\">    ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">subscribeToFriendStatus</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span> handleStatusChange<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 keyword\">return</span> <span class=\"token keyword\">function</span> <span class=\"token function\">cleanup</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">      ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">unsubscribeFromFriendStatus</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span> handleStatusChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>isOnline <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\">return</span> <span class=\"token string\">'Загрузка...'</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token keyword\">return</span> isOnline <span class=\"token operator\">?</span> <span class=\"token string\">'В сети'</span> <span class=\"token operator\">:</span> <span class=\"token string\">'Не в сети'</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p><strong>Зачем мы вернули функцию из нашего эффекта?</strong> Это необязательный механизм сброса эффектов. Каждый эффект может возвратить функцию, которая сбросит его. Это даёт нам возможность объединить вместе логику оформления и отмены подписки. Они, всё-таки, часть одного и того же эффекта!</p>\n<p><strong>Когда именно React будет сбрасывать эффект?</strong> React будет сбрасывать эффект перед тем, как компонент размонтируется. Однако, как мы уже знаем, эффекты выполняются не один раз, а при каждом рендере. Вот почему React <em>также</em> сбрасывает эффект из предыдущего рендера, перед тем, как запустить следующий. Мы рассмотрим <a href=\"#explanation-why-effects-run-on-each-update\">почему это позволяет избежать багов</a> и <a href=\"#tip-optimizing-performance-by-skipping-effects\">как отказаться от этой логики, если это вызывает проблемы с производительностью</a> далее.</p>\n<blockquote>\n<p>Совет</p>\n<p>Нам не нужно возвращать именованную функцию из эффекта. Мы назвали её «сбросом», чтобы объяснить её предназначение. Вы можете по желанию возвратить стрелочную функцию или назвать её как-то по-другому.</p>\n</blockquote>\n<h2 id=\"recap\"><a href=\"#recap\" 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>Мы узнали, что с помощью <code class=\"gatsby-code-text\">useEffect</code>, мы можем вызывать разные побочные эффекты после того, как компонент отрендерится. Некоторым эффектам нужен сброс, поэтому они возвращают соответствующую функцию.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\">  <span class=\"token function\">useEffect</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">function</span> <span class=\"token function\">handleStatusChange</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">status</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token function\">setIsOnline</span><span class=\"token punctuation\">(</span>status<span class=\"token punctuation\">.</span>isOnline<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">subscribeToFriendStatus</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span> handleStatusChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">unsubscribeFromFriendStatus</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span> handleStatusChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><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 function\">useEffect</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    document<span class=\"token punctuation\">.</span>title <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Вы нажали </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>count<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> раз</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Хук эффекта покрывает оба сценария единым API.</p>\n<hr>\n<p><strong>Если вы чувствуете, что вы достаточно разобрались с тем, как работает хук эффекта, вы можете отправиться <a href=\"/docs/hooks-rules.html\">на страницу о правилах хуков</a> прямо сейчас.</strong></p>\n<hr>\n<h2 id=\"tips-for-using-effects\"><a href=\"#tips-for-using-effects\" 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>Сейчас, давайте углубимся в некоторые особенности хука <code class=\"gatsby-code-text\">useEffect</code>, о которых опытные пользователи React наверняка уже задумались. Пожалуйста, не заставляйте себя углубляться в эти особенности прямо сейчас. Вы можете сперва закрепить выше пройденный материал и вернуться сюда позже в любой момент.</p>\n<h3 id=\"tip-use-multiple-effects-to-separate-concerns\"><a href=\"#tip-use-multiple-effects-to-separate-concerns\" 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>Совет: используйте разные хуки для разных задач </h3>\n<p>Один из ключевых моментов, которые мы описали в <a href=\"/docs/hooks-intro.html#complex-components-become-hard-to-understand\">мотивации</a>, приводит аргументы о том, что в отличии от хуков, классовые методы жизненного цикла часто содержат логику, которая никак между собой не связана, в то время как связанная логика, разбивается на несколько методов. Далее мы приведём пример компонента, который объединяет в себе логику счётчика и индикатора статуса нашего друга из предыдущих примеров:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">class</span> <span class=\"token class-name\">FriendStatusWithCounter</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> count<span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> isOnline<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>handleStatusChange <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">handleStatusChange</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\">componentDidMount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    document<span class=\"token punctuation\">.</span>title <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Вы нажали </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>count<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> раз</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n    ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">subscribeToFriendStatus</span><span class=\"token punctuation\">(</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleStatusChange\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">componentDidUpdate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    document<span class=\"token punctuation\">.</span>title <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Вы нажали </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>count<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> раз</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">componentWillUnmount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">unsubscribeFromFriendStatus</span><span class=\"token punctuation\">(</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleStatusChange\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">handleStatusChange</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">status</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <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>\n      isOnline<span class=\"token operator\">:</span> status<span class=\"token punctuation\">.</span>isOnline\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n  <span class=\"token comment\">// ...</span></code></pre></div>\n<p>Обратите внимание, что логика, которая устанавливает <code class=\"gatsby-code-text\">document.title</code> разбита между <code class=\"gatsby-code-text\">componentDidMount</code> и <code class=\"gatsby-code-text\">componentDidUpdate</code>. Логика подписки также раскидана между <code class=\"gatsby-code-text\">componentDidMount</code> и <code class=\"gatsby-code-text\">componentWillUnmount</code>. А метод <code class=\"gatsby-code-text\">componentDidMount</code> включает в себя логику для обеих задач.</p>\n<p>Как же можно решить эту проблему с помощью хуков? Точно так же, как <a href=\"/docs/hooks-state.html#tip-using-multiple-state-variables\">вы можете использовать хук <em>состояния</em> более одного раза</a>, вы можете использовать и несколько эффектов. Это даёт нам возможность разделять разную несвязанную между собой логику между разными эффектами.</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\">function</span> <span class=\"token function\">FriendStatusWithCounter</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\">const</span> <span class=\"token punctuation\">[</span>count<span class=\"token punctuation\">,</span> setCount<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token number\">0</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token function\">useEffect</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span>    document<span class=\"token punctuation\">.</span>title <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Вы нажали </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>count<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> раз</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>isOnline<span class=\"token punctuation\">,</span> setIsOnline<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token function\">useEffect</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span>    <span class=\"token keyword\">function</span> <span class=\"token function\">handleStatusChange</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">status</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token function\">setIsOnline</span><span class=\"token punctuation\">(</span>status<span class=\"token punctuation\">.</span>isOnline<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n\n    ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">subscribeToFriendStatus</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span> handleStatusChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">unsubscribeFromFriendStatus</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span> handleStatusChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><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><strong>С помощью хуков, мы можем разделить наш код основываясь на том, что он делает</strong>, а не по принципам методов жизненного цикла. React будет выполнять <em>каждый</em> используемый эффект в компоненте, согласно порядку их объявления.</p>\n<h3 id=\"explanation-why-effects-run-on-each-update\"><a href=\"#explanation-why-effects-run-on-each-update\" 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>Объяснение: почему эффекты выполняются при каждом обновлении </h3>\n<p>Если вы привыкли пользоваться классами, вам может быть не совсем ясно, почему этап сброса эффекта происходит после каждого последующего рендера, а не один лишь раз во время размонтирования. Давайте рассмотрим на практике, почему такой подход помогает создавать компоненты с меньшим количеством багов.</p>\n<p><a href=\"#example-using-classes-1\">Ранее на этой странице</a>, мы рассматривали пример с компонентом <code class=\"gatsby-code-text\">FriendStatus</code>, который отображает в сети наш друг или нет. Наш класс берёт <code class=\"gatsby-code-text\">friend.id</code> из <code class=\"gatsby-code-text\">this.props</code>, подписывается на статус друга после того, как компонент смонтировался, и отписывается во время размонтирования.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\">  <span class=\"token function\">componentDidMount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">subscribeToFriendStatus</span><span class=\"token punctuation\">(</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleStatusChange\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">componentWillUnmount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">unsubscribeFromFriendStatus</span><span class=\"token punctuation\">(</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleStatusChange\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span></code></pre></div>\n<p><strong>Но что же произойдёт, если проп <code class=\"gatsby-code-text\">friend</code> поменяется</strong>, пока компонент все ещё находится на экране? Наш компонент будет отображать статус в сети уже какого-нибудь другого друга. Это как раз таки баг. Это также может привести к утечке памяти или вообще к вылету нашего приложения при размонтировании, так как метод отписки будет использовать неправильный ID друга, от которого мы хотим отписаться.</p>\n<p>В классовом компоненте нам бы пришлось добавить <code class=\"gatsby-code-text\">componentDidUpdate</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 function\">componentDidMount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">subscribeToFriendStatus</span><span class=\"token punctuation\">(</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleStatusChange\n    <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 function\">componentDidUpdate</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">prevProps</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token comment\">// Отписаться от предыдущего friend.id</span></span><span class=\"gatsby-highlight-code-line\">    ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">unsubscribeFromFriendStatus</span><span class=\"token punctuation\">(</span></span><span class=\"gatsby-highlight-code-line\">      prevProps<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleStatusChange</span><span class=\"gatsby-highlight-code-line\">    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token comment\">// Подписаться на следующий friend.id</span></span><span class=\"gatsby-highlight-code-line\">    ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">subscribeToFriendStatus</span><span class=\"token punctuation\">(</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleStatusChange</span><span class=\"gatsby-highlight-code-line\">    <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\">componentWillUnmount</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">unsubscribeFromFriendStatus</span><span class=\"token punctuation\">(</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span>\n      <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>handleStatusChange\n    <span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span></code></pre></div>\n<p>Не использовать <code class=\"gatsby-code-text\">componentDidUpdate</code> надлежащим образом — это один из самых распространённых источников багов в приложениях React.</p>\n<p>Теперь давайте рассмотрим версию этого же компонента, но уже написанного с использованием хуков:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">function</span> <span class=\"token function\">FriendStatus</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 comment\">// ...</span>\n  <span class=\"token function\">useEffect</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// ...</span>\n    ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">subscribeToFriendStatus</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span> handleStatusChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n      ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">unsubscribeFromFriendStatus</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span> handleStatusChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Этого бага в данном компоненте нет. (Но мы и не изменили там ничего)</p>\n<p>Здесь нет никакого особого кода для решения проблем с обновлениями, так как <code class=\"gatsby-code-text\">useEffect</code> решает их <em>по умолчанию</em>. Он сбрасывает предыдущие эффекты прежде чем выполнить новые. Чтобы показать это на практике, давайте рассмотрим последовательность подписок и отписок, которые этот компонент может выполнить в течение некоторого времени.</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token comment\">// Монтируем с пропсами { friend: { id: 100 } } </span>\nChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">subscribeToFriendStatus</span><span class=\"token punctuation\">(</span><span class=\"token number\">100</span><span class=\"token punctuation\">,</span> handleStatusChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>     <span class=\"token comment\">// Выполняем первый эффект</span>\n\n<span class=\"token comment\">// Обновляем с пропсами { friend: { id: 200 } }</span>\nChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">unsubscribeFromFriendStatus</span><span class=\"token punctuation\">(</span><span class=\"token number\">100</span><span class=\"token punctuation\">,</span> handleStatusChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Сбрасываем предыдущий эффект</span>\nChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">subscribeToFriendStatus</span><span class=\"token punctuation\">(</span><span class=\"token number\">200</span><span class=\"token punctuation\">,</span> handleStatusChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>     <span class=\"token comment\">// Выполняем следующий эффект</span>\n\n<span class=\"token comment\">// Обновляем с пропсами { friend: { id: 300 } }</span>\nChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">unsubscribeFromFriendStatus</span><span class=\"token punctuation\">(</span><span class=\"token number\">200</span><span class=\"token punctuation\">,</span> handleStatusChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Сбрасываем предыдущий эффект</span>\nChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">subscribeToFriendStatus</span><span class=\"token punctuation\">(</span><span class=\"token number\">300</span><span class=\"token punctuation\">,</span> handleStatusChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>     <span class=\"token comment\">// Выполняем следующий эффект</span>\n\n<span class=\"token comment\">// Размонтируем</span>\nChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">unsubscribeFromFriendStatus</span><span class=\"token punctuation\">(</span><span class=\"token number\">300</span><span class=\"token punctuation\">,</span> handleStatusChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Сбрасываем последний эффект</span></code></pre></div>\n<p>Эта логика по умолчанию гарантирует согласованность выполняемых нами действий и исключает баги, распространённые в классовых компонентах из-за упущенной логики обновления.</p>\n<h3 id=\"tip-optimizing-performance-by-skipping-effects\"><a href=\"#tip-optimizing-performance-by-skipping-effects\" 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>Совет: оптимизация производительности за счёт пропуска эффектов </h3>\n<p>В некоторых случаях сброс или выполнение эффекта при каждом рендере может вызвать проблему с производительностью. В классовых компонентах, мы можем решить это используя дополнительное сравнение <code class=\"gatsby-code-text\">prevProps</code> или <code class=\"gatsby-code-text\">prevState</code> внутри <code class=\"gatsby-code-text\">componentDidUpdate</code>:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token function\">componentDidUpdate</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">prevProps<span class=\"token punctuation\">,</span> prevState</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>prevState<span class=\"token punctuation\">.</span>count <span class=\"token operator\">!==</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>count<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    document<span class=\"token punctuation\">.</span>title <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Вы нажали </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span><span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>state<span class=\"token punctuation\">.</span>count<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> раз</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Эту логику приходится использовать довольно часто, поэтому мы решили встроить её в API хука <code class=\"gatsby-code-text\">useEffect</code>. Вы можете сделать так, чтобы React <em>пропускал</em> вызов эффекта, если определённые значения остались без изменений между последующими рендерами. Чтобы сделать это, передайте массив в <code class=\"gatsby-code-text\">useEffect</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 function\">useEffect</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  document<span class=\"token punctuation\">.</span>title <span class=\"token operator\">=</span> <span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">Вы нажали </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>count<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> раз</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span>count<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Перезапускать эффект только если count поменялся</span></span></code></pre></div>\n<p>В этом примере, мы передаём <code class=\"gatsby-code-text\">[count]</code> вторым аргументом. Что это вообще значит? Это значит, что если <code class=\"gatsby-code-text\">count</code> будет равен <code class=\"gatsby-code-text\">5</code> и наш компонент повторно рендерится с тем же значением <code class=\"gatsby-code-text\">count</code> = <code class=\"gatsby-code-text\">5</code>, React сравнит <code class=\"gatsby-code-text\">[5]</code> из предыдущего рендера и <code class=\"gatsby-code-text\">[5]</code> из следующего рендера. Так как, все элементы массива остались без изменений (<code class=\"gatsby-code-text\">5 === 5</code>), React пропустит этот эффект. Это и есть оптимизация данного процесса.</p>\n<p>Когда при следующем рендере наша переменная <code class=\"gatsby-code-text\">count</code> обновится до <code class=\"gatsby-code-text\">6</code>, React сравнит элементы в массиве <code class=\"gatsby-code-text\">[5]</code> из предыдущего рендера и элементы массива <code class=\"gatsby-code-text\">[6]</code> из следующего рендера. На этот раз, React выполнит наш эффект, так как <code class=\"gatsby-code-text\">5 !== 6</code>. Если у вас будет несколько элементов в массиве, React будет выполнять наш эффект, в том случае, когда хотя бы один из них будет отличаться.</p>\n<p>Это также работает для эффектов с этапом сброса:</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 function\">useEffect</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">function</span> <span class=\"token function\">handleStatusChange</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">status</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">setIsOnline</span><span class=\"token punctuation\">(</span>status<span class=\"token punctuation\">.</span>isOnline<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">subscribeToFriendStatus</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span> handleStatusChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    ChatAPI<span class=\"token punctuation\">.</span><span class=\"token function\">unsubscribeFromFriendStatus</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">,</span> handleStatusChange<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">;</span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span>props<span class=\"token punctuation\">.</span>friend<span class=\"token punctuation\">.</span>id<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Повторно подписаться, только если props.friend.id изменился</span></span></code></pre></div>\n<p>В будущем, второй аргумент возможно будет добавляться автоматически с помощью трансформации во время выполнения.</p>\n<blockquote>\n<p>Примечание</p>\n<p>Если вы хотите использовать эту оптимизацию, обратите внимание на то, чтобы массив включал в себя <strong>все значения из области видимости компонента (такие как пропсы и состояние), которые могут изменяться с течением времени, и которые будут использоваться эффектом</strong>. В противном случае, ваш код будет ссылаться на устаревшее значение из предыдущих рендеров. Отдельные страницы документации рассказывают о том, <a href=\"/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies\">как поступить с функциями</a> и <a href=\"/docs/hooks-faq.html#what-can-i-do-if-my-effect-dependencies-change-too-often\">что делать с часто изменяющимися массивами</a>.</p>\n<p>Если вы хотите запустить эффект и сбросить его только один раз (при монтировании и размонтировании), вы можете передать пустой массив (<code class=\"gatsby-code-text\">[]</code>) вторым аргументом. React посчитает, что ваш эффект не зависит от <em>каких-либо</em> значений из пропсов или состояния и поэтому не будет выполнять повторных рендеров. Это не обрабатывается как особый случай — он напрямую следует из логики работы массивов зависимостей.</p>\n<p>Если вы передадите пустой массив (<code class=\"gatsby-code-text\">[]</code>), пропсы и состояние внутри эффекта всегда будут иметь значения, присвоенные им изначально. Хотя передача <code class=\"gatsby-code-text\">[]</code> ближе по модели мышления к знакомым <code class=\"gatsby-code-text\">componentDidMount</code> и <code class=\"gatsby-code-text\">componentWillUnmount</code>, обычно есть <a href=\"/docs/hooks-faq.html#is-it-safe-to-omit-functions-from-the-list-of-dependencies\">более хорошие</a> <a href=\"/docs/hooks-faq.html#what-can-i-do-if-my-effect-dependencies-change-too-often\">способы</a> избежать частых повторных рендеров. Не забывайте, что React откладывает выполнение <code class=\"gatsby-code-text\">useEffect</code>, пока браузер не отрисует все изменения, поэтому выполнение дополнительной работы не является существенной проблемой.</p>\n<p>Мы рекомендуем использовать правило <a href=\"https://github.com/facebook/react/issues/14920\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">exhaustive-deps</code></a>, входящее в наш пакет правил линтера <a href=\"https://www.npmjs.com/package/eslint-plugin-react-hooks#installation\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">eslint-plugin-react-hooks</code></a>. Оно предупреждает, когда зависимости указаны неправильно и предлагает исправление.</p>\n</blockquote>\n<h2 id=\"next-steps\"><a href=\"#next-steps\" 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>Поздравляем! Это была длинная страница, но мы надеемся, что под конец, у нас получилось ответить на все ваши вопросы по поводу работы эффектов. Вы уже узнали о хуке состояния и о хуке эффекта, и теперь есть <em>очень много</em> вещей, которые вы можете делать, объединив их вместе. Они покрывают большинство задач решаемых классами. В остальных случаях, вам могут пригодиться <a href=\"/docs/hooks-reference.html\">дополнительные хуки</a>.</p>\n<p>Мы также узнали, как хуки избавляют от проблем описанных в <a href=\"/docs/hooks-intro.html#motivation\">мотивации</a>. Мы увидели, как с помощью сброса эффектов нам удаётся избежать повторов кода в <code class=\"gatsby-code-text\">componentDidUpdate</code> и <code class=\"gatsby-code-text\">componentWillUnmount</code>, объединить связанный код вместе и защитить наш код от багов. Мы также рассмотрели, как можно разделять наши эффекты по смыслу и назначению, что ранее было невозможно в классах.</p>\n<p>На этом этапе, вы, возможно, задаётесь вопросом, как хуки работают в целом. Как React понимает, какая переменная состояния соответствует какому вызову <code class=\"gatsby-code-text\">useState</code> между повторными рендерами? Как React «сопоставляет» предыдущие и следующие эффекты при каждом обновлении? <strong>На следующей странице, мы узнаем о <a href=\"/docs/hooks-rules.html\">правилах хуков</a>, так как они являются залогом правильной работы хуков.</strong></p>","frontmatter":{"title":"Использование хука эффекта","next":"hooks-rules.html","prev":"hooks-state.html"},"fields":{"path":"content/docs/hooks-effect.md","slug":"docs/hooks-effect.html"}}},"pageContext":{"slug":"docs/hooks-effect.html"}},"staticQueryHashes":[]}