{"componentChunkName":"component---src-templates-docs-js","path":"/docs/hooks-faq.html","result":{"data":{"markdownRemark":{"html":"<p><em>Хуки</em> — нововведение в React 16.8, которое позволяет использовать состояние и другие возможности React без написания классов.</p>\n<p>На этой странице вы найдёте ответы на популярные вопросы о <a href=\"/docs/hooks-overview.html\">хуках</a>.</p>\n<!--\n  if you ever need to regenerate this, this snippet in the devtools console might help:\n\n  $$('.anchor').map(a =>\n    `${' '.repeat(2 * +a.parentNode.nodeName.slice(1))}` +\n    `[${a.parentNode.textContent}](${a.getAttribute('href')})`\n  ).join('\\n')\n-->\n<ul>\n<li>\n<p><a href=\"#adoption-strategy\">Внедрение хуков</a></p>\n<ul>\n<li><a href=\"#which-versions-of-react-include-hooks\">В какой версии React появились хуки?</a></li>\n<li><a href=\"#do-i-need-to-rewrite-all-my-class-components\">Нужно ли переписать все мои классовые компоненты?</a></li>\n<li><a href=\"#what-can-i-do-with-hooks-that-i-couldnt-with-classes\">Что можно сделать с помощью хуков, чего невозможно добиться, используя классы?</a></li>\n<li><a href=\"#how-much-of-my-react-knowledge-stays-relevant\">Какая часть моих знаний о React всё ещё актуальна?</a></li>\n<li><a href=\"#should-i-use-hooks-classes-or-a-mix-of-both\">Что мне использовать: хуки, классы или оба подхода?</a></li>\n<li><a href=\"#do-hooks-cover-all-use-cases-for-classes\">Дают ли хуки все возможности классов?</a></li>\n<li><a href=\"#do-hooks-replace-render-props-and-higher-order-components\">Являются ли хуки заменой рендер-пропсам и компонентам высшего порядка?</a></li>\n<li><a href=\"#what-do-hooks-mean-for-popular-apis-like-redux-connect-and-react-router\">Как хуки повлияют на популярные API, такие как Redux <code class=\"gatsby-code-text\">connect()</code> и React Router?</a></li>\n<li><a href=\"#do-hooks-work-with-static-typing\">Поддерживают ли хуки статическую типизацию?</a></li>\n<li><a href=\"#how-to-test-components-that-use-hooks\">Как тестировать компоненты, которые используют хуки?</a></li>\n<li><a href=\"#what-exactly-do-the-lint-rules-enforce\">Что конкретно проверяют правила линтера в хуках?</a></li>\n</ul>\n</li>\n<li>\n<p><a href=\"#from-classes-to-hooks\">От классов к хукам</a></p>\n<ul>\n<li><a href=\"#how-do-lifecycle-methods-correspond-to-hooks\">Как методы жизненного цикла соответствуют хукам?</a></li>\n<li><a href=\"#how-can-i-do-data-fetching-with-hooks\">Как осуществлять запросы данных с помощью хуков?</a></li>\n<li><a href=\"#is-there-something-like-instance-variables\">Существует что-нибудь наподобие полей экземпляра?</a></li>\n<li><a href=\"#should-i-use-one-or-many-state-variables\">Сколько переменных состояния я могу использовать — одну или несколько?</a></li>\n<li><a href=\"#can-i-run-an-effect-only-on-updates\">Могу ли я использовать эффект только на обновлениях компонента?</a></li>\n<li><a href=\"#how-to-get-the-previous-props-or-state\">Как получить предыдущие пропсы или состояние?</a></li>\n<li><a href=\"#why-am-i-seeing-stale-props-or-state-inside-my-function\">Почему я вижу устаревшие пропсы или состояние в моей функции?</a></li>\n<li><a href=\"#how-do-i-implement-getderivedstatefromprops\">Как я могу реализовать <code class=\"gatsby-code-text\">getDerivedStateFromProps</code>?</a></li>\n<li><a href=\"#is-there-something-like-forceupdate\">Существует что-нибудь наподобие forceUpdate?</a></li>\n<li><a href=\"#can-i-make-a-ref-to-a-function-component\">Могу ли я изменить реф, переданный в функциональный компонент?</a></li>\n<li><a href=\"#how-can-i-measure-a-dom-node\">Как я могу измерить узел DOM?</a></li>\n<li><a href=\"#what-does-const-thing-setthing--usestate-mean\">Что значит <code class=\"gatsby-code-text\">const [thing, setThing] = useState()</code>?</a></li>\n</ul>\n</li>\n<li>\n<p><a href=\"#performance-optimizations\">Оптимизации производительности</a></p>\n<ul>\n<li><a href=\"#can-i-skip-an-effect-on-updates\">Могу ли я пропустить эффект при обновлениях?</a></li>\n<li><a href=\"#is-it-safe-to-omit-functions-from-the-list-of-dependencies\">Безопасно ли не указывать функции в списке зависимостей?</a></li>\n<li><a href=\"#what-can-i-do-if-my-effect-dependencies-change-too-often\">Что делать, если зависимости эффекта изменяются слишком часто?</a></li>\n<li><a href=\"#how-do-i-implement-shouldcomponentupdate\">Как я могу реализовать <code class=\"gatsby-code-text\">shouldComponentUpdate</code>?</a></li>\n<li><a href=\"#how-to-memoize-calculations\">Как закешировать вычисления?</a></li>\n<li><a href=\"#how-to-create-expensive-objects-lazily\">Как лениво создавать большие объекты?</a></li>\n<li><a href=\"#are-hooks-slow-because-of-creating-functions-in-render\">Являются ли хуки медленными из-за создания функций на каждом рендере?</a></li>\n<li><a href=\"#how-to-avoid-passing-callbacks-down\">Как избежать передачи колбэков вниз?</a></li>\n<li><a href=\"#how-to-read-an-often-changing-value-from-usecallback\">Как получить часто изменяемое значение из хука <code class=\"gatsby-code-text\">useCallback</code>?</a></li>\n</ul>\n</li>\n<li>\n<p><a href=\"#under-the-hood\">Под капотом</a></p>\n<ul>\n<li><a href=\"#how-does-react-associate-hook-calls-with-components\">Как React связывает вызовы хуков с компонентом?</a></li>\n<li><a href=\"#what-is-the-prior-art-for-hooks\">Что послужило прообразом хуков?</a></li>\n</ul>\n</li>\n</ul>\n<h2 id=\"adoption-strategy\"><a href=\"#adoption-strategy\" 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<h3 id=\"which-versions-of-react-include-hooks\"><a href=\"#which-versions-of-react-include-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>В какой версии React появились хуки? </h3>\n<p>Начиная с релиза 16.8.0, React включает в себя стабильную реализацию хуков для:</p>\n<ul>\n<li>React DOM</li>\n<li>React Native</li>\n<li>React DOM Server</li>\n<li>React Test Renderer</li>\n<li>React Shallow Renderer</li>\n</ul>\n<p>Обратите внимание, что <strong>хуки будут доступны, только если все React-пакеты версии 16.8.0 или выше</strong>. Хуки не будут работать, если вы, например, забыли обновить React DOM.</p>\n<p><a href=\"https://facebook.github.io/react-native/blog/2019/03/12/releasing-react-native-059\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">React Native 0.59</a> и выше поддерживает хуки.</p>\n<h3 id=\"do-i-need-to-rewrite-all-my-class-components\"><a href=\"#do-i-need-to-rewrite-all-my-class-components\" 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#gradual-adoption-strategy\">не собираемся</a> удалять классы из React, поскольку никто не может позволить себе такой глобальный рефакторинг. Мы советуем пробовать хуки только в новом коде.</p>\n<h3 id=\"what-can-i-do-with-hooks-that-i-couldnt-with-classes\"><a href=\"#what-can-i-do-with-hooks-that-i-couldnt-with-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>Хуки дают новый мощный способ повторного использования кода в компонентах. <a href=\"/docs/hooks-custom.html\">«Создание пользовательских хуков»</a> даёт представление об их возможностях. <a href=\"https://medium.com/@dan_abramov/making-sense-of-react-hooks-fdbde8803889\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Эта статья</a>, написанная одним из участников команды React, описывает новые возможности, которые открывают хуки.</p>\n<h3 id=\"how-much-of-my-react-knowledge-stays-relevant\"><a href=\"#how-much-of-my-react-knowledge-stays-relevant\" 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 всё ещё актуальна? </h3>\n<p>Хуки — это новый способ использовать возможности React, которые вы уже знаете: состояние, жизненный цикл, контекст и рефы. Хуки не изменили фундаментальную логику React, поэтому ваши знания компонентов, пропсов и нисходящего потока данных остаются актуальными.</p>\n<p>Однако, хуки — не самая простая часть React. Если вам чего-то не хватает в этой документации, <a href=\"https://github.com/reactjs/reactjs.org/issues/new\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">дайте нам знать</a>, и мы постараемся вам помочь.</p>\n<h3 id=\"should-i-use-hooks-classes-or-a-mix-of-both\"><a href=\"#should-i-use-hooks-classes-or-a-mix-of-both\" 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>Вы не можете использовать хуки <em>внутри</em> классового компонента, но вы можете комбинировать классы и функциональные компоненты с хуками в одном дереве. Является ли компонент классовым или функциональным с использованием хуков — неважно, это всего лишь особенность реализации. Мы ожидаем, что в будущем хуки станут главным способом написания React-компонентов.</p>\n<h3 id=\"do-hooks-cover-all-use-cases-for-classes\"><a href=\"#do-hooks-cover-all-use-cases-for-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>Наша главная задача, чтобы хуки покрывали всю функциональность классов в ближайшем будущем. Пока не существует хуков, реализующих методы жизненного цикла <code class=\"gatsby-code-text\">getSnapshotBeforeUpdate</code>, <code class=\"gatsby-code-text\">getDerivedStateFromError</code> и <code class=\"gatsby-code-text\">componentDidCatch</code>, но мы планируем скоро их добавить.</p>\n<p>Хуки появились совсем недавно, и некоторые сторонние библиотеки могут быть ещё не совместимы с ними.</p>\n<h3 id=\"do-hooks-replace-render-props-and-higher-order-components\"><a href=\"#do-hooks-replace-render-props-and-higher-order-components\" 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\">renderItem</code> или компонент-контейнер может иметь разные рендер-пропсы для различных слотов). Но в большинстве случаев хуки должны помочь уменьшить вложенность компонентов в вашем дереве.</p>\n<h3 id=\"what-do-hooks-mean-for-popular-apis-like-redux-connect-and-react-router\"><a href=\"#what-do-hooks-mean-for-popular-apis-like-redux-connect-and-react-router\" 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>Как хуки повлияют на популярные API, такие как Redux <code class=\"gatsby-code-text\">connect()</code> и React Router? </h3>\n<p>Вы можете продолжить использовать тот же самый API, который вы использовали — всё продолжит работать как прежде.</p>\n<p>Начиная с версии 7.1.0, React Redux <a href=\"https://react-redux.js.org/api/hooks\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">поддерживает API хуков</a> и предоставляет такие хуки как <code class=\"gatsby-code-text\">useDispatch</code> и <code class=\"gatsby-code-text\">useSelector</code>.</p>\n<p>Начиная с версии 5.1 появилась <a href=\"https://reacttraining.com/react-router/web/api/Hooks\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">поддержка хуков</a> в React Router.</p>\n<p>В будущем другие библиотеки могут также начать поддерживать хуки.</p>\n<h3 id=\"do-hooks-work-with-static-typing\"><a href=\"#do-hooks-work-with-static-typing\" 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 для Flow и TypeScript поддерживают хуки.</p>\n<p>Заметьте, что пользовательские хуки дают вам возможность накладывать ограничения на API React, если вы хотите типизировать их более строго каким-то образом. React предоставляет примитивы, которые вы можете комбинировать по своему усмотрению даже такими способами, которые и не были изначально предусмотрены.</p>\n<h3 id=\"how-to-test-components-that-use-hooks\"><a href=\"#how-to-test-components-that-use-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>С точки зрения React, компонент, использующий хуки, является обычным компонентом. Если ваш способ тестирования не опирается на внутреннюю реализацию React, тестирование компонентов с хуками не должно отличатся от тестирования других компонентов.</p>\n<blockquote>\n<p>Примечание</p>\n<p><a href=\"/docs/testing-recipes.html\">Рецепты Тестирования</a> включают в себя множество примеров, которые вы можете скопировать себе.</p>\n</blockquote>\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  <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 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\">\n      </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\">\n      </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\">\n        Кликни меня\n      </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\">\n    </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>Мы будем тестировать этот компонент с помощью React DOM. Чтобы убедиться, что поведение совпадает с тем, что случится в браузере, мы обернём код рендера и обновления в вызов <a href=\"/docs/test-utils.html#act\"><code class=\"gatsby-code-text\">ReactTestUtils.act()</code></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\">import</span> React <span class=\"token keyword\">from</span> <span class=\"token string\">'react'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> ReactDOM <span class=\"token keyword\">from</span> <span class=\"token string\">'react-dom'</span><span class=\"token punctuation\">;</span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span> act <span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'react-dom/test-utils'</span><span class=\"token punctuation\">;</span></span><span class=\"token keyword\">import</span> Counter <span class=\"token keyword\">from</span> <span class=\"token string\">'./Counter'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">let</span> container<span class=\"token punctuation\">;</span>\n\n<span class=\"token function\">beforeEach</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  container <span class=\"token operator\">=</span> document<span class=\"token punctuation\">.</span><span class=\"token function\">createElement</span><span class=\"token punctuation\">(</span><span class=\"token string\">'div'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  document<span class=\"token punctuation\">.</span>body<span class=\"token punctuation\">.</span><span class=\"token function\">appendChild</span><span class=\"token punctuation\">(</span>container<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\n<span class=\"token function\">afterEach</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>body<span class=\"token punctuation\">.</span><span class=\"token function\">removeChild</span><span class=\"token punctuation\">(</span>container<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  container <span class=\"token operator\">=</span> <span class=\"token keyword\">null</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 function\">it</span><span class=\"token punctuation\">(</span><span class=\"token string\">'can render and update a counter'</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<span class=\"gatsby-highlight-code-line\">  <span class=\"token function\">act</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\">    ReactDOM<span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Counter</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">,</span> container<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>  <span class=\"token keyword\">const</span> button <span class=\"token operator\">=</span> container<span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">'button'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> label <span class=\"token operator\">=</span> container<span class=\"token punctuation\">.</span><span class=\"token function\">querySelector</span><span class=\"token punctuation\">(</span><span class=\"token string\">'p'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>label<span class=\"token punctuation\">.</span>textContent<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Вы кликнули 0 раз'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>document<span class=\"token punctuation\">.</span>title<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Вы кликнули 0 раз'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token comment\">// Тестируем второй рендер и эффект</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token function\">act</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\">    button<span class=\"token punctuation\">.</span><span class=\"token function\">dispatchEvent</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">MouseEvent</span><span class=\"token punctuation\">(</span><span class=\"token string\">'click'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">{</span>bubbles<span class=\"token operator\">:</span> <span class=\"token boolean\">true</span><span class=\"token punctuation\">}</span><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 class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>  <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>label<span class=\"token punctuation\">.</span>textContent<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Вы кликнули 1 раз'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token function\">expect</span><span class=\"token punctuation\">(</span>document<span class=\"token punctuation\">.</span>title<span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">toBe</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Вы кликнули 1 раз'</span><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>Вызовы <code class=\"gatsby-code-text\">act()</code> также запустят эффекты внутри.</p>\n<p>Если вам надо протестировать пользовательский хук, вы можете создать компонент в ваших тестах и использовать в нём этот хук. После этого вы можете протестировать сам компонент.</p>\n<p>Для уменьшения однотипного кода, мы советуем использовать библиотеку <a href=\"https://testing-library.com/react\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">React Testing Library</a>. Она была создана для написания тестов, использующих ваши компоненты и имитирующих поведение пользователей в браузере.</p>\n<p>За более подробной информацией обратитесь к <a href=\"/docs/testing-recipes.html\">Рецептам Тестирования</a>.</p>\n<h3 id=\"what-exactly-do-the-lint-rules-enforce\"><a href=\"#what-exactly-do-the-lint-rules-enforce\" 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>Что конкретно проверяют <a href=\"https://www.npmjs.com/package/eslint-plugin-react-hooks\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">правила линтера</a> в хуках?</h3>\n<p>Мы предоставляем <a href=\"https://www.npmjs.com/package/eslint-plugin-react-hooks\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">плагин к ESLint</a>, который принуждает следовать <a href=\"/docs/hooks-rules.html\">правилам хуков</a>, чтобы избежать ошибок. Подразумевается, что любая функция, имя который начинается с «<code class=\"gatsby-code-text\">use</code>» и заглавной буквы далее, является хуком. Мы понимаем, что это предположение не идеальное, и могут случаться ложные срабатывания. Однако, без этого важного соглашения, было бы невозможно заставить хуки работать хорошо, а более длинные имена могли бы помешать людям начать использовать хуки или следовать соглашению.</p>\n<p>Правила линтера проверяют, что:</p>\n<ul>\n<li>Вызовы хуков происходят либо внутри функции с именем, написанном в стиле <code class=\"gatsby-code-text\">PascalCase</code> (подразумевается, что это компонент), либо внутри другой функции <code class=\"gatsby-code-text\">useSomething</code> (подразумевается, что это пользовательский хук).</li>\n<li>Хуки вызываются в одном и том же порядке при каждом рендере.</li>\n</ul>\n<p>Существует ещё несколько предположений, которые могут измениться по мере того, как мы будем регулировать правила и искать баланс между нахождением ошибок и ложными срабатываниями.</p>\n<h2 id=\"from-classes-to-hooks\"><a href=\"#from-classes-to-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>От классов к хукам </h2>\n<h3 id=\"how-do-lifecycle-methods-correspond-to-hooks\"><a href=\"#how-do-lifecycle-methods-correspond-to-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<ul>\n<li><code class=\"gatsby-code-text\">constructor</code>: Функциональному компоненту не нужен конструктор. Вы можете инициализировать состояние, используя вызов <a href=\"/docs/hooks-reference.html#usestate\"><code class=\"gatsby-code-text\">useState</code></a>. Если вычисления состояния затратны, вы можете передать функцию в <code class=\"gatsby-code-text\">useState</code>.</li>\n<li><code class=\"gatsby-code-text\">getDerivedStateFromProps</code>: Запланировать обновление <a href=\"#how-do-i-implement-getderivedstatefromprops\">при рендере</a>.</li>\n<li><code class=\"gatsby-code-text\">shouldComponentUpdate</code>: Смотрите объяснение <code class=\"gatsby-code-text\">React.memo</code> <a href=\"#how-do-i-implement-shouldcomponentupdate\">ниже</a>.</li>\n<li><code class=\"gatsby-code-text\">render</code>: Это тело функционального компонента.</li>\n<li><code class=\"gatsby-code-text\">componentDidMount</code>, <code class=\"gatsby-code-text\">componentDidUpdate</code>, <code class=\"gatsby-code-text\">componentWillUnmount</code>: <a href=\"/docs/hooks-reference.html#useeffect\">Хук <code class=\"gatsby-code-text\">useEffect</code></a> заменяет все их комбинации (включая <a href=\"#can-i-skip-an-effect-on-updates\">более</a> <a href=\"#can-i-run-an-effect-only-on-updates\">редкие</a> случаи).</li>\n<li><code class=\"gatsby-code-text\">getSnapshotBeforeUpdate</code>, <code class=\"gatsby-code-text\">componentDidCatch</code> и <code class=\"gatsby-code-text\">getDerivedStateFromError</code>: В данный момент не существует хуков-аналогов для этих методов, но они будут скоро добавлены.</li>\n</ul>\n<h3 id=\"how-can-i-do-data-fetching-with-hooks\"><a href=\"#how-can-i-do-data-fetching-with-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>Посмотрите <a href=\"https://codesandbox.io/s/jvvkoo8pq3\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">небольшое демо</a>, а затем ознакомьтесь <a href=\"https://www.robinwieruch.de/react-hooks-fetch-data/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">со статьёй</a>, которая рассказывает как делать запросы данных с помощью хуков.</p>\n<h3 id=\"is-there-something-like-instance-variables\"><a href=\"#is-there-something-like-instance-variables\" 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-reference.html#useref\"><code class=\"gatsby-code-text\">useRef()</code></a> может использоваться не только для DOM-рефов. Реф — это общий контейнер, а его свойство <code class=\"gatsby-code-text\">current</code> — изменяемое и может хранить любое значение, подобно свойству экземпляра класса.</p>\n<p>Вы можете использовать его внутри <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 keyword\">function</span> <span class=\"token function\">Timer</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\">const</span> intervalRef <span class=\"token operator\">=</span> <span class=\"token function\">useRef</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></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 keyword\">const</span> id <span class=\"token operator\">=</span> <span class=\"token function\">setInterval</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    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"gatsby-highlight-code-line\">    intervalRef<span class=\"token punctuation\">.</span>current <span class=\"token operator\">=</span> id<span class=\"token punctuation\">;</span></span>    <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      <span class=\"token function\">clearInterval</span><span class=\"token punctuation\">(</span>intervalRef<span class=\"token punctuation\">.</span>current<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\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Для объявления интервала нам не понадобится реф (<code class=\"gatsby-code-text\">id</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 comment\">// ...</span>\n  <span class=\"token keyword\">function</span> <span class=\"token function\">handleCancelClick</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 function\">clearInterval</span><span class=\"token punctuation\">(</span>intervalRef<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>  <span class=\"token punctuation\">}</span>\n  <span class=\"token comment\">// ...</span></code></pre></div>\n<p>В целом вы можете рассматривать рефы как свойства экземпляра класса. Старайтесь избегать установки рефов во время рендера, пока вы не реализуете <a href=\"#how-to-create-expensive-objects-lazily\">ленивую инициализацию</a>, так как это может привести к неожиданному поведению. Как правило, вы будете изменять рефы в обработчиках событий и эффектах.</p>\n<h3 id=\"should-i-use-one-or-many-state-variables\"><a href=\"#should-i-use-one-or-many-state-variables\" 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\">useState()</code> однократно и сразу сохранить всё состояние в одном объекте. Да, вы можете так сделать. Взгляните на пример компонента, который следует за движением курсора. Мы храним позицию и размер этого компонента в локальном состоянии.</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\">Box</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>state<span class=\"token punctuation\">,</span> setState<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> left<span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> top<span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> width<span class=\"token operator\">:</span> <span class=\"token number\">100</span><span class=\"token punctuation\">,</span> height<span class=\"token operator\">:</span> <span class=\"token number\">100</span> <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>Допустим, мы хотим написать некоторую логику, которая будет изменять значения <code class=\"gatsby-code-text\">left</code> и <code class=\"gatsby-code-text\">top</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 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 keyword\">function</span> <span class=\"token function\">handleWindowMouseMove</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">      <span class=\"token comment\">// Использование \"...state\" гарантирует, что мы не потеряем width и height</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token function\">setState</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">state</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> <span class=\"token operator\">...</span>state<span class=\"token punctuation\">,</span> left<span class=\"token operator\">:</span> e<span class=\"token punctuation\">.</span>pageX<span class=\"token punctuation\">,</span> top<span class=\"token operator\">:</span> e<span class=\"token punctuation\">.</span>pageY <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>    <span class=\"token punctuation\">}</span>\n    <span class=\"token comment\">// Примечание: эта реализация немного упрощена</span>\n    window<span class=\"token punctuation\">.</span><span class=\"token function\">addEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mousemove'</span><span class=\"token punctuation\">,</span> handleWindowMouseMove<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> window<span class=\"token punctuation\">.</span><span class=\"token function\">removeEventListener</span><span class=\"token punctuation\">(</span><span class=\"token string\">'mousemove'</span><span class=\"token punctuation\">,</span> handleWindowMouseMove<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><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token comment\">// ...</span></code></pre></div>\n<p>Код написан так, потому что мы обновляем переменную состояния, <em>заменяя</em> её значение. Данное поведение отличается от <code class=\"gatsby-code-text\">this.setState</code>, ведь этот классовый метод <em>объединяет</em> изменённые поля с текущим объектом состояния.</p>\n<p>Если вам не хватает автоматического объединения состояния, вы можете написать свой хук <code class=\"gatsby-code-text\">useLegacyState</code>, который объединяет обновления состояния объекта. Однако, вместо этого <strong>мы рекомендуем разделять состояние на несколько переменных, учитывая, какие свойства логически относятся друг к другу и будут изменяться вместе.</strong></p>\n<p>Например, мы можем разделить состояние нашего компонента на объекты <code class=\"gatsby-code-text\">position</code> и <code class=\"gatsby-code-text\">size</code>, что поможет всегда изменять только <code class=\"gatsby-code-text\">position</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\">function</span> <span class=\"token function\">Box</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\">const</span> <span class=\"token punctuation\">[</span>position<span class=\"token punctuation\">,</span> setPosition<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> left<span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> top<span class=\"token operator\">:</span> <span class=\"token number\">0</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>size<span class=\"token punctuation\">,</span> setSize<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> width<span class=\"token operator\">:</span> <span class=\"token number\">100</span><span class=\"token punctuation\">,</span> height<span class=\"token operator\">:</span> <span class=\"token number\">100</span> <span class=\"token punctuation\">}</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    <span class=\"token keyword\">function</span> <span class=\"token function\">handleWindowMouseMove</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">e</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">      <span class=\"token function\">setPosition</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> left<span class=\"token operator\">:</span> e<span class=\"token punctuation\">.</span>pageX<span class=\"token punctuation\">,</span> top<span class=\"token operator\">:</span> e<span class=\"token punctuation\">.</span>pageY <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>    <span class=\"token punctuation\">}</span>\n    <span class=\"token comment\">// ...</span></code></pre></div>\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 keyword\">function</span> <span class=\"token function\">Box</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\">const</span> position <span class=\"token operator\">=</span> <span class=\"token function\">useWindowPosition</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>size<span class=\"token punctuation\">,</span> setSize<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> width<span class=\"token operator\">:</span> <span class=\"token number\">100</span><span class=\"token punctuation\">,</span> height<span class=\"token operator\">:</span> <span class=\"token number\">100</span> <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>\n\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">function</span> <span class=\"token function\">useWindowPosition</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span>  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>position<span class=\"token punctuation\">,</span> setPosition<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> left<span class=\"token operator\">:</span> <span class=\"token number\">0</span><span class=\"token punctuation\">,</span> top<span class=\"token operator\">:</span> <span class=\"token number\">0</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</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  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">return</span> position<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Обратите внимание, как мы смогли вынести вызов <code class=\"gatsby-code-text\">useState</code>, изменяющий <code class=\"gatsby-code-text\">position</code>, и соответствующих эффект в отдельный хук, практически не меняя их код. Если бы всё состояние хранилось в одном объекте, сделать это перемещение было бы на порядок сложнее.</p>\n<p>На самом деле, оба варианта имеют право на жизнь. Однако, компоненты будут более читаемыми, если вы найдёте баланс между двумя подходами и будете группировать связанные друг с другом данные. Если работа с состоянием становится сложной, мы советуем <a href=\"/docs/hooks-reference.html#usereducer\">использовать редюсер</a> или выносить логику в отдельные хуки.</p>\n<h3 id=\"can-i-run-an-effect-only-on-updates\"><a href=\"#can-i-run-an-effect-only-on-updates\" 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=\"#is-there-something-like-instance-variables\">использовать изменяемый реф</a>, чтобы вручную хранить логическое значение, показывающее, прошёл ли первый рендер. В свою очередь эффект может опираться на это значение. Если вы замечаете, что эта логика нужна вам часто, вы можете вынести её в отдельный хук.</p>\n<h3 id=\"how-to-get-the-previous-props-or-state\"><a href=\"#how-to-get-the-previous-props-or-state\" 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=\"#is-there-something-like-instance-variables\">используя реф</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\">Counter</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 keyword\">const</span> prevCountRef <span class=\"token operator\">=</span> <span class=\"token function\">useRef</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</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=\"gatsby-highlight-code-line\">    prevCountRef<span class=\"token punctuation\">.</span>current <span class=\"token operator\">=</span> count<span class=\"token punctuation\">;</span></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\">const</span> prevCount <span class=\"token operator\">=</span> prevCountRef<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">;</span></span>\n  <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 punctuation\">{</span>count<span class=\"token punctuation\">}</span><span class=\"token plain-text\">, до этого: </span><span class=\"token punctuation\">{</span>prevCount<span class=\"token punctuation\">}</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>\n<span class=\"token punctuation\">}</span></code></pre></div>\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 keyword\">function</span> <span class=\"token function\">Counter</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<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> prevCount <span class=\"token operator\">=</span> <span class=\"token function\">usePrevious</span><span class=\"token punctuation\">(</span>count<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>  <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 punctuation\">{</span>count<span class=\"token punctuation\">}</span><span class=\"token plain-text\">, до этого: </span><span class=\"token punctuation\">{</span>prevCount<span class=\"token punctuation\">}</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>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">function</span> <span class=\"token function\">usePrevious</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">value</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span>  <span class=\"token keyword\">const</span> ref <span class=\"token operator\">=</span> <span class=\"token function\">useRef</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</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    ref<span class=\"token punctuation\">.</span>current <span class=\"token operator\">=</span> value<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 keyword\">return</span> ref<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\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 keyword\">function</span> <span class=\"token function\">Counter</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 keyword\">const</span> calculation <span class=\"token operator\">=</span> count <span class=\"token operator\">+</span> <span class=\"token number\">100</span><span class=\"token punctuation\">;</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> prevCalculation <span class=\"token operator\">=</span> <span class=\"token function\">usePrevious</span><span class=\"token punctuation\">(</span>calculation<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>  <span class=\"token comment\">// ...</span></code></pre></div>\n<p>Возможно, в будущем API React введёт хук <code class=\"gatsby-code-text\">usePrevious</code>, так как он требуется довольно часто.</p>\n<p>Также смотрите <a href=\"#how-do-i-implement-getderivedstatefromprops\">рекомендованный паттерн для производного состояния</a>.</p>\n<h3 id=\"why-am-i-seeing-stale-props-or-state-inside-my-function\"><a href=\"#why-am-i-seeing-stale-props-or-state-inside-my-function\" 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\">render()</code>, в которой она была создана. Рассмотрим такой код:</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 keyword\">function</span> <span class=\"token function\">handleAlertClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">setTimeout</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 function\">alert</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Вы кликнули по: '</span> <span class=\"token operator\">+</span> count<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token number\">3000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\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\">\n      </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\">\n      </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\">\n        Кликни меня\n      </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\">\n      </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>handleAlertClick<span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n        Показать предупреждение\n      </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\">\n    </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>Если вы сперва кликните по «Показать предупреждение», а потом увеличите счётчик, то предупреждение отобразит значение переменной <code class=\"gatsby-code-text\">count</code> <strong>на момент нажатия по кнопке «Показать предупреждение»</strong>. Такое поведение предотвращает баги в коде, который предполагает, что пропсы и состояние не меняются.</p>\n<p>Если вы намеренно хотите считать из асинхронного колбэка <em>свежайшее</em> состояние, вы можете сперва сохранить его <a href=\"/docs/hooks-faq.html#is-there-something-like-instance-variables\">в реф</a>, потом изменить его и затем считать его из рефа.</p>\n<p>Наконец, возможна другая ситуация, почему вы видите устаревшие пропсы или состояние: когда вы используете оптимизацию с помощью «массива зависимостей», но неправильно указали какие-то зависимости. Например, если эффект передаёт вторым параметром <code class=\"gatsby-code-text\">[]</code>, но при этом использует <code class=\"gatsby-code-text\">someProp</code>, то он продолжит «видеть» исходное значение <code class=\"gatsby-code-text\">someProp</code>. Правильным решением является либо исправление массива, либо отказ от его использования.\nПо этим ссылкам описаны <a href=\"#is-it-safe-to-omit-functions-from-the-list-of-dependencies\">подходы к функциям</a> в аналогичных ситуациях и <a href=\"#what-can-i-do-if-my-effect-dependencies-change-too-often\">другие известные способы</a> снижения частоты вызова эффектов, исключающие передачу неправильных зависимостей.</p>\n<blockquote>\n<p>Примечание</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<h3 id=\"how-do-i-implement-getderivedstatefromprops\"><a href=\"#how-do-i-implement-getderivedstatefromprops\" 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>Как я могу реализовать <code class=\"gatsby-code-text\">getDerivedStateFromProps</code>? </h3>\n<p>Несмотря на то, что вам скорее всего <a href=\"/blog/2018/06/07/you-probably-dont-need-derived-state.html\">это не нужно</a>, в редких случаях (например, для реализации компонента <code class=\"gatsby-code-text\">&lt;Transition&gt;</code>), вы можете изменять состояние прямо во время рендера. React моментально сделает повторный рендер компонента с обновлённым состоянием сразу после первого рендера, и это не будет затратно.</p>\n<p>В этом примере, мы храним предыдущее значение пропа <code class=\"gatsby-code-text\">row</code> в состоянии, что позволяет сравнить значения:</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\">ScrollView</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span>row<span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>isScrollingDown<span class=\"token punctuation\">,</span> setIsScrollingDown<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token boolean\">false</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>prevRow<span class=\"token punctuation\">,</span> setPrevRow<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=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>row <span class=\"token operator\">!==</span> prevRow<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token comment\">// Row изменился с прошлого рендера. Обновляем isScrollingDown.</span>\n    <span class=\"token function\">setIsScrollingDown</span><span class=\"token punctuation\">(</span>prevRow <span class=\"token operator\">!==</span> <span class=\"token keyword\">null</span> <span class=\"token operator\">&amp;&amp;</span> row <span class=\"token operator\">></span> prevRow<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">setPrevRow</span><span class=\"token punctuation\">(</span>row<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">return</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>isScrollingDown<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Сперва это может показаться странным, но изменение во время рендера — это именно то, чем всегда концептуально являлся метод <code class=\"gatsby-code-text\">getDerivedStateFromProps</code>.</p>\n<h3 id=\"is-there-something-like-forceupdate\"><a href=\"#is-there-something-like-forceupdate\" 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>Существует что-нибудь наподобие forceUpdate? </h3>\n<p>Оба хука <code class=\"gatsby-code-text\">useState</code> и <code class=\"gatsby-code-text\">useReducer</code> <a href=\"/docs/hooks-reference.html#bailing-out-of-a-state-update\">игнорируют обновления</a>, если следующее значение равно предыдущему. Мутация состояния и вызов <code class=\"gatsby-code-text\">setState</code> не приведут к повторному рендеру.</p>\n<p>Обычно, вы не должны мутировать внутреннее состояние в React. Однако, в качестве лазейки, вы можете использовать увеличивающийся счётчик, чтобы заставить компонент повторно рендериться, если состояние не изменилось:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\">  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>ignored<span class=\"token punctuation\">,</span> forceUpdate<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useReducer</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">x</span> <span class=\"token operator\">=></span> x <span class=\"token operator\">+</span> <span class=\"token number\">1</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 keyword\">function</span> <span class=\"token function\">handleClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">forceUpdate</span><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>Старайтесь избегать этого подхода, если возможно.</p>\n<h3 id=\"can-i-make-a-ref-to-a-function-component\"><a href=\"#can-i-make-a-ref-to-a-function-component\" 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-reference.html#useimperativehandle\"><code class=\"gatsby-code-text\">useImperativeHandle</code></a>.</p>\n<h3 id=\"how-can-i-measure-a-dom-node\"><a href=\"#how-can-i-measure-a-dom-node\" 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>Как я могу измерить узел DOM? </h3>\n<p>Один из элементарных способов определения положения или размера DOM-узла это использование <a href=\"/docs/refs-and-the-dom.html#callback-refs\">колбэк-реф</a>. React будет вызывать этот колбэк всякий раз, когда реф привязывается к другому узлу. Вот <a href=\"https://codesandbox.io/s/l7m0v5x4v9\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">небольшая демонстрация</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\">MeasureExample</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>height<span class=\"token punctuation\">,</span> setHeight<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 keyword\">const</span> measuredRef <span class=\"token operator\">=</span> <span class=\"token function\">useCallback</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">node</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node <span class=\"token operator\">!==</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token function\">setHeight</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span><span class=\"token function\">getBoundingClientRect</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>height<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 class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><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></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<span class=\"gatsby-highlight-code-line\"><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 attr-name\">ref</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>measuredRef<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>h1</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span></span><span class=\"token plain-text\">      </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h2</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Заголовок выше имеет высоту </span><span class=\"token punctuation\">{</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">round</span><span class=\"token punctuation\">(</span>height<span class=\"token punctuation\">)</span><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>h2</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></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>Мы не выбрали <code class=\"gatsby-code-text\">useRef</code> в этом примере, потому что объект рефа не уведомляет нас об <em>изменениях</em> текущего значения рефа. Использование колбэк-рефа гарантирует, что <a href=\"https://codesandbox.io/s/818zzk8m78\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">даже если дочерний компонент отображает измеренный узел позже</a> (например, в ответ на клик), мы по-прежнему получаем уведомление об этом в родительском компоненте и можем обновлять измерения.</p>\n<p>Обратите внимание, что мы передаём <code class=\"gatsby-code-text\">[]</code> как массив зависимостей в <code class=\"gatsby-code-text\">useCallback</code>. Это гарантирует, что наш колбэк-реф не изменится между повторными рендерами, а значит React не будет вызывать его без необходимости.</p>\n<p>В данном примере колбэк-реф будет вызван только при монтировании и размонтировании компонента, хотя отрендеренный компонент <code class=\"gatsby-code-text\">&lt;h1&gt;</code> остаётся на месте при последующих повторных рендерах. Если необходимо отследить изменение размера компонента, воспользуйтесь <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"><code class=\"gatsby-code-text\">ResizeObserver</code></a> или сторонним хуком, использующий этот API.</p>\n<p>При желании вы можете <a href=\"https://codesandbox.io/s/m5o42082xy\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">извлечь эту логику</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\">MeasureExample</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\">const</span> <span class=\"token punctuation\">[</span>rect<span class=\"token punctuation\">,</span> ref<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useClientRect</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>  <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></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>h1</span> <span class=\"token attr-name\">ref</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>ref<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>h1</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\"></span>\n<span class=\"token plain-text\">      </span><span class=\"token punctuation\">{</span>rect <span class=\"token operator\">!==</span> <span class=\"token keyword\">null</span> <span class=\"token operator\">&amp;&amp;</span>\n      <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span>h2</span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">Заголовок выше имеет высоту </span><span class=\"token punctuation\">{</span>Math<span class=\"token punctuation\">.</span><span class=\"token function\">round</span><span class=\"token punctuation\">(</span>rect<span class=\"token punctuation\">.</span>height<span class=\"token punctuation\">)</span><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>h2</span><span class=\"token punctuation\">></span></span>\n      <span class=\"token punctuation\">}</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></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\n<span class=\"token keyword\">function</span> <span class=\"token function\">useClientRect</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>rect<span class=\"token punctuation\">,</span> setRect<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=\"token keyword\">const</span> ref <span class=\"token operator\">=</span> <span class=\"token function\">useCallback</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">node</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>node <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 function\">setRect</span><span class=\"token punctuation\">(</span>node<span class=\"token punctuation\">.</span><span class=\"token function\">getBoundingClientRect</span><span class=\"token punctuation\">(</span><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 punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</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>rect<span class=\"token punctuation\">,</span> ref<span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<h3 id=\"what-does-const-thing-setthing--usestate-mean\"><a href=\"#what-does-const-thing-setthing--usestate-mean\" 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>Что значит <code class=\"gatsby-code-text\">const [thing, setThing] = useState()</code>? </h3>\n<p>Если вы не знакомы с этим синтаксисом, ознакомьтесь с <a href=\"/docs/hooks-state.html#tip-what-do-square-brackets-mean\">объяснением</a> в документации хука состояния.</p>\n<h2 id=\"performance-optimizations\"><a href=\"#performance-optimizations\" 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<h3 id=\"can-i-skip-an-effect-on-updates\"><a href=\"#can-i-skip-an-effect-on-updates\" 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-reference.html#conditionally-firing-an-effect\">условным вызовом эффектов</a>. Обратите внимание, что забыв обработать обновления, вы зачастую можете <a href=\"/docs/hooks-effect.html#explanation-why-effects-run-on-each-update\">создать ошибки</a>. Поэтому это и не является поведением по умолчанию.</p>\n<h3 id=\"is-it-safe-to-omit-functions-from-the-list-of-dependencies\"><a href=\"#is-it-safe-to-omit-functions-from-the-list-of-dependencies\" 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=\"token keyword\">function</span> <span class=\"token function\">Example</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> someProp <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">function</span> <span class=\"token function\">doSomething</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>someProp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></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    <span class=\"token function\">doSomething</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 punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 🔴 Так делать небезопасно (вызывать `doSomething`, который использует `someProp`)</span></span><span class=\"token punctuation\">}</span></code></pre></div>\n<p>Сложно помнить, какие пропсы и состояние используются функцией определённой вне эффекта. Именно поэтому, <strong>лучше объявлять функции нужные эффекту <em>внутри</em> него</strong>. Тогда легче увидеть, от каких значений из области видимости компонента зависит эффект:</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\">Example</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> someProp <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</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 keyword\">function</span> <span class=\"token function\">doSomething</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">      console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>someProp<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token function\">doSomething</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 punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span>someProp<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// ✅ Правильно (наш эффект использует только `someProp`)</span></span><span class=\"token punctuation\">}</span></code></pre></div>\n<p>Если после такого изменения мы видим, что никакие значения из области видимости компонента не используются, то можно безопасно указать <code class=\"gatsby-code-text\">[]</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  <span class=\"token keyword\">function</span> <span class=\"token function\">doSomething</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Привет'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token function\">doSomething</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 punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// ✅ Так можно поступить в этом примере, потому что</span></span><span class=\"gatsby-highlight-code-line\">        <span class=\"token comment\">// нет зависимости от значений из области видимости компонента</span></span></code></pre></div>\n<p>В зависимости от ситуации, может пригодиться один из вариантов, описанных ниже.</p>\n<blockquote>\n<p>Примечание</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<p>Давайте разберёмся, почему это важно.</p>\n<p>Когда вы указываете <a href=\"/docs/hooks-reference.html#conditionally-firing-an-effect\">список зависимостей</a> через последний аргумент хуков <code class=\"gatsby-code-text\">useEffect</code>, <code class=\"gatsby-code-text\">useLayoutEffect</code>, <code class=\"gatsby-code-text\">useMemo</code>, <code class=\"gatsby-code-text\">useCallback</code> или <code class=\"gatsby-code-text\">useImperativeHandle</code>, в него должны войти все использованные значения, которые задействованы в потоке данных React, включая пропсы, состояние и их производные.</p>\n<p>Безопасно опускать в списке <strong>только</strong> те функции, которые не используют ни сами, ни через функции, которые они вызывают, пропсы, состояние или их производные. Так, в следующем примере показан баг:</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\">ProductPage</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> productId <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>product<span class=\"token punctuation\">,</span> setProduct<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=\"token keyword\">async</span> <span class=\"token keyword\">function</span> <span class=\"token function\">fetchProduct</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\">const</span> response <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://myapi/product/'</span> <span class=\"token operator\">+</span> productId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Использует проп productId</span></span>    <span class=\"token keyword\">const</span> json <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> response<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token function\">setProduct</span><span class=\"token punctuation\">(</span>json<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <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    <span class=\"token function\">fetchProduct</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 punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 🔴 Неправильно, потому что `fetchProduct` использует `productId`</span></span>  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p><strong>Рекомендовано исправлять такой код, перемещая функцию <em>внутрь</em> вашего эффекта</strong>. Это помогает замечать, какие пропсы и состояние используются вашим эффектом, и убедиться, что они перечислены в списке зависимостей:</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\">ProductPage</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> productId <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>product<span class=\"token punctuation\">,</span> setProduct<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=\"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=\"gatsby-highlight-code-line\">    <span class=\"token comment\">// Переместив эту функцию внутрь эффекта, мы ясно видим, какие значения она использует.</span></span><span class=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">async</span> <span class=\"token keyword\">function</span> <span class=\"token function\">fetchProduct</span><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 keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://myapi/product/'</span> <span class=\"token operator\">+</span> productId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span><span class=\"gatsby-highlight-code-line\">      <span class=\"token keyword\">const</span> json <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> response<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><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 function\">setProduct</span><span class=\"token punctuation\">(</span>json<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\">fetchProduct</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 punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span>productId<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// ✅ Правильно, потому что эффект использует только productId</span></span>  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\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=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">let</span> ignore <span class=\"token operator\">=</span> <span class=\"token boolean\">false</span><span class=\"token punctuation\">;</span></span>    <span class=\"token keyword\">async</span> <span class=\"token keyword\">function</span> <span class=\"token function\">fetchProduct</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http://myapi/product/'</span> <span class=\"token operator\">+</span> productId<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n      <span class=\"token keyword\">const</span> json <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> response<span class=\"token punctuation\">.</span><span class=\"token function\">json</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 operator\">!</span>ignore<span class=\"token punctuation\">)</span> <span class=\"token function\">setProduct</span><span class=\"token punctuation\">(</span>json<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>    <span class=\"token punctuation\">}</span>\n    <span class=\"token function\">fetchProduct</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><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span> ignore <span class=\"token operator\">=</span> <span class=\"token boolean\">true</span> <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>productId<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span></code></pre></div>\n<p>Мы переместили функцию внутрь эффекта, так что её не нужно указывать в списке зависимостей.</p>\n<blockquote>\n<p>Совет</p>\n<p>Посмотрите <a href=\"https://codesandbox.io/s/jvvkoo8pq3\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">этот небольшой пример</a> и <a href=\"https://www.robinwieruch.de/react-hooks-fetch-data/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">эту статью</a>, чтобы узнать больше о загрузке данных с помощью хуков.</p>\n</blockquote>\n<p><strong>Если по какой-то причине вы <em>не</em> можете переместить функцию в эффект, есть другие варианты:</strong></p>\n<ul>\n<li><strong>Можно попробовать поместить функцию снаружи компонента</strong>. В таком случае она гарантированно не будет ссылаться на пропсы и состояние, так что её не требуется перечислять в списке зависимостей.</li>\n<li>Если функция, которую вы вызываете, является чистым вычислением и её безопасно вызывать во время рендера, вы можете <strong>вызвать её снаружи эффекта, а не внутри</strong>, и сделать эффект зависящим от результата этого вызова, а не от самой функции.</li>\n<li>В крайнем случае можете <strong>добавить саму функцию в список зависимостей эффекта, но <em>обернув её определение</em></strong> в хук <a href=\"/docs/hooks-reference.html#usecallback\"><code class=\"gatsby-code-text\">useCallback</code></a>. Тогда функция будет оставаться неизменной, до тех пор, пока не изменятся её зависимости:</li>\n</ul>\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\">ProductPage</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> productId <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token comment\">// ✅ Оборачиваем в useCallback, чтобы избежать изменений при каждом рендере</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> fetchProduct <span class=\"token operator\">=</span> <span class=\"token function\">useCallback</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\">// ... Что-то делаем с productId ...</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span>productId<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// ✅ Перечисляем все зависимости useCallback</span></span>\n  <span class=\"token keyword\">return</span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">ProductDetails</span></span> <span class=\"token attr-name\">fetchProduct</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>fetchProduct<span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">function</span> <span class=\"token function\">ProductDetails</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> fetchProduct <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</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 function\">fetchProduct</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 punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span>fetchProduct<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// ✅ Перечисляем все зависимости useEffect</span></span>  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Заметьте, что в примере выше мы всё ещё <strong>должны</strong> указать функцию в списке зависимостей. Тогда гарантируется, что изменение пропа <code class=\"gatsby-code-text\">productId</code> у <code class=\"gatsby-code-text\">ProductPage</code> приведёт к повторному запрашиванию данных в компоненте <code class=\"gatsby-code-text\">ProductDetails</code>.</p>\n<h3 id=\"what-can-i-do-if-my-effect-dependencies-change-too-often\"><a href=\"#what-can-i-do-if-my-effect-dependencies-change-too-often\" 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=\"token keyword\">function</span> <span class=\"token function\">Counter</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    <span class=\"token keyword\">const</span> id <span class=\"token operator\">=</span> <span class=\"token function\">setInterval</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=\"gatsby-highlight-code-line\">      <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 class=\"token comment\">// Этот эффект зависит от переменной состояния `count`</span></span>    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1000</span><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 function\">clearInterval</span><span class=\"token punctuation\">(</span>id<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><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// 🔴 Баг: `count` не указан в качестве зависимости</span></span>\n  <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 punctuation\">{</span>count<span class=\"token punctuation\">}</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>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Пустой набор зависимостей <code class=\"gatsby-code-text\">[]</code> означает, что эффект будет выполняться только один раз, когда компонент монтируется, а не при каждом повторном рендере. Проблема в том, что внутри обратного вызова <code class=\"gatsby-code-text\">setInterval</code> значение <code class=\"gatsby-code-text\">count</code> не изменяется, потому что мы создали замыкание со значением <code class=\"gatsby-code-text\">count</code>, установленным в <code class=\"gatsby-code-text\">0</code>, как это было при выполнении обратного вызова эффекта. Каждую секунду этот обратный вызов вызывает <code class=\"gatsby-code-text\">setCount(0 + 1)</code>, поэтому счетчик никогда не превышает 1.</p>\n<p>Если переписать список зависимостей как <code class=\"gatsby-code-text\">[count]</code>, то баг будет устранён, но это приведёт к сбрасыванию интервала при каждом изменении. Такое поведение может быть нежелательно. Чтобы исправить это, мы можем применить <a href=\"/docs/hooks-reference.html#functional-updates\">форму функционального обновления хука <code class=\"gatsby-code-text\">setState</code></a>, которая позволяет указать, <em>как</em> должно меняться состояние, не ссылаясь явно на <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=\"token keyword\">function</span> <span class=\"token function\">Counter</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    <span class=\"token keyword\">const</span> id <span class=\"token operator\">=</span> <span class=\"token function\">setInterval</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=\"gatsby-highlight-code-line\">      <span class=\"token function\">setCount</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">c</span> <span class=\"token operator\">=></span> c <span class=\"token operator\">+</span> <span class=\"token number\">1</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// ✅ Эта строчка не зависит от внешней переменной `count`</span></span>    <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token number\">1000</span><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 function\">clearInterval</span><span class=\"token punctuation\">(</span>id<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><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// ✅ Наш эффект не использует никаких переменных из области видимости компонента</span></span>\n  <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 punctuation\">{</span>count<span class=\"token punctuation\">}</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>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>(Идентичность функции <code class=\"gatsby-code-text\">setCount</code> гарантирована, поэтому её можно безопасно не включать в список зависимостей.)</p>\n<p>Теперь обратный вызов <code class=\"gatsby-code-text\">setInterval</code> выполняется один раз в секунду, но каждый раз, когда внутренний вызов <code class=\"gatsby-code-text\">setCount</code> может использовать обновленное значение для <code class=\"gatsby-code-text\">count</code> (называемое <code class=\"gatsby-code-text\">c</code> в обратном вызове здесь.)</p>\n<p>В более сложных случаях (например, когда одно состояние зависит от другого), попробуйте перенести логику обновления состояния из хука эффекта в хук <a href=\"/docs/hooks-reference.html#usereducer\"><code class=\"gatsby-code-text\">useReducer</code></a>. <a href=\"https://adamrackis.dev/state-and-use-reducer/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Эта статья</a> иллюстрирует пример того, как это сделать. <strong>Идентичность функции <code class=\"gatsby-code-text\">dispatch</code> из хука <code class=\"gatsby-code-text\">useReducer</code> всегда стабильна</strong> — даже если функция редюсера объявлена внутри компонента и считывает его пропсы.</p>\n<p>В крайнем случае если вы хотите реализовать что-то наподобие <code class=\"gatsby-code-text\">this</code> в классах, вы можете <a href=\"/docs/hooks-faq.html#is-there-something-like-instance-variables\">использовать реф</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\">Example</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=\"gatsby-highlight-code-line\">  <span class=\"token comment\">// Сохраняем свежайшие значения пропсов в ref</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> latestProps <span class=\"token operator\">=</span> <span class=\"token function\">useRef</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</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\">    latestProps<span class=\"token punctuation\">.</span>current <span class=\"token operator\">=</span> props<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 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\">tick</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 comment\">// Считываем свежайшие значения пропсов в любое время</span></span><span class=\"gatsby-highlight-code-line\">      console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span>latestProps<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>    <span class=\"token punctuation\">}</span>\n\n    <span class=\"token keyword\">const</span> id <span class=\"token operator\">=</span> <span class=\"token function\">setInterval</span><span class=\"token punctuation\">(</span>tick<span class=\"token punctuation\">,</span> <span class=\"token number\">1000</span><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 function\">clearInterval</span><span class=\"token punctuation\">(</span>id<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><span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Этот эффект никогда не исполняется повторно</span></span><span class=\"token punctuation\">}</span></code></pre></div>\n<p>Рекомендуется прибегать к этому подходу только если не удалось найти лучшей альтернативы, поскольку компоненты, полагающиеся на изменчивость, менее предсказуемы. Если какой-то конкретный паттерн плохо получается выразить, <a href=\"https://github.com/facebook/react/issues/new\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">откройте ишью на GitHub</a> с примером исполняемого кода и мы постараемся помочь.</p>\n<h3 id=\"how-do-i-implement-shouldcomponentupdate\"><a href=\"#how-do-i-implement-shouldcomponentupdate\" 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>Как я могу реализовать <code class=\"gatsby-code-text\">shouldComponentUpdate</code>? </h3>\n<p>Вы можете обернуть функциональный компонент в вызов <code class=\"gatsby-code-text\">React.memo</code> для поверхностного сравнения его пропсов:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">const</span> Button <span class=\"token operator\">=</span> React<span class=\"token punctuation\">.</span><span class=\"token function\">memo</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">props</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// ваш компонент</span>\n<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Это функция не является хуком, так как она не ведёт себя как хук. <code class=\"gatsby-code-text\">React.memo</code> аналогична <code class=\"gatsby-code-text\">PureComponent</code>, но она сравнивает только пропсы. (Вы также можете добавить второй аргумент, чтобы определить свою функцию сравнения, которая примет старые и новые пропсы. Если эта функция вернёт <code class=\"gatsby-code-text\">true</code>, обновление будет пропущено.)</p>\n<p><code class=\"gatsby-code-text\">React.memo</code> не сравнивает состояние, потому что не существует единого объекта, который можно сравнить. Но вы можете также сделать дочерние компоненты чистыми или даже <a href=\"/docs/hooks-faq.html#how-to-memoize-calculations\">оптимизировать определённые дочерние компоненты, используя хук <code class=\"gatsby-code-text\">useMemo</code></a>.</p>\n<h3 id=\"how-to-memoize-calculations\"><a href=\"#how-to-memoize-calculations\" 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-reference.html#usememo\"><code class=\"gatsby-code-text\">useMemo</code></a> позволяет вам закешировать вычисления между несколькими рендерами, путём запоминания прошлого результата:</p>\n<div class=\"gatsby-highlight\" data-language=\"jsx\"><pre class=\"gatsby-code-jsx\"><code class=\"gatsby-code-jsx\"><span class=\"token keyword\">const</span> memoizedValue <span class=\"token operator\">=</span> <span class=\"token function\">useMemo</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\">computeExpensiveValue</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">)</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span>a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n<p>Этот код вызовет <code class=\"gatsby-code-text\">computeExpensiveValue(a, b)</code>. Но если зависимости <code class=\"gatsby-code-text\">[a, b]</code> не изменились с прошлого рендера, <code class=\"gatsby-code-text\">useMemo</code> пропустит повторный вызов и повторно использует значения, которые он вернул в прошлый раз.</p>\n<p>Помните, что функция, передаваемая в <code class=\"gatsby-code-text\">useMemo</code>, выполняется во время рендера. Не стоит делать в ней что-то, что вы обычно не делаете во время рендера. Например, побочные эффекты выполняются в хуке <code class=\"gatsby-code-text\">useEffect</code>, а не в <code class=\"gatsby-code-text\">useMemo</code>.</p>\n<p><strong>Рассматриваете <code class=\"gatsby-code-text\">useMemo</code>, как оптимизацию производительности, но не стоит полагаться на неё на 100%.</strong> В будущем React сможет <code class=\"gatsby-code-text\">забыть</code> прошлые закешированные значения и провести перерасчёт на следующем рендере, например, для освобождения памяти, занятой компонентами вне экрана. Пишите ваш код так, чтобы он мог работать без <code class=\"gatsby-code-text\">useMemo</code>, и только тогда добавляйте оптимизацию производительности. (Для редких случаев, когда значение <strong>не должно никогда</strong> пересчитываться, вы можете <a href=\"#how-to-create-expensive-objects-lazily\">лениво инициализировать</a> реф.)</p>\n<p>Также удобно, что <code class=\"gatsby-code-text\">useMemo</code> позволяет пропускать затратные повторные рендеры дочерних компонентов:</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\">Parent</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span> a<span class=\"token punctuation\">,</span> b <span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Рендерится повторно, только если `a` изменится:</span>\n  <span class=\"token keyword\">const</span> child1 <span class=\"token operator\">=</span> <span class=\"token function\">useMemo</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Child1</span></span> <span class=\"token attr-name\">a</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>a<span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span>a<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token comment\">// Рендерится повторно, только если `b` изменится:</span>\n  <span class=\"token keyword\">const</span> child2 <span class=\"token operator\">=</span> <span class=\"token function\">useMemo</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">Child2</span></span> <span class=\"token attr-name\">b</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>b<span class=\"token punctuation\">}</span></span> <span class=\"token punctuation\">/></span></span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span>b<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></span><span class=\"token punctuation\">></span></span><span class=\"token plain-text\">\n      </span><span class=\"token punctuation\">{</span>child1<span class=\"token punctuation\">}</span><span class=\"token plain-text\">\n      </span><span class=\"token punctuation\">{</span>child2<span class=\"token punctuation\">}</span><span class=\"token plain-text\">\n    </span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span></span><span class=\"token punctuation\">></span></span>\n  <span class=\"token punctuation\">)</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Обратите внимание, что этот подход не будет работать внутри циклов, так как вызовы хуков <a href=\"/docs/hooks-rules.html\">не могут</a> быть помещены внутрь циклов. Но вы можете создать отдельный компонент для элемента списка, и вызвать <code class=\"gatsby-code-text\">useMemo</code> там.</p>\n<h3 id=\"how-to-create-expensive-objects-lazily\"><a href=\"#how-to-create-expensive-objects-lazily\" 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\">useMemo</code> позволяет вам <a href=\"#how-to-memoize-calculations\">закешировать ресурсозатратные вычисления</a>, если зависимости не изменились. Однако, этот способ <strong>не гарантирует</strong>, что повторных вычислений не случится. Иногда вам нужно удостовериться, что объект будет создан только один раз.</p>\n<p><strong>Первый частый вариант использования — создание изначального состояния затратно:</strong></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\">Table</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\">// ⚠️ createRows() вызывается на каждом рендере</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>rows<span class=\"token punctuation\">,</span> setRows<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token function\">createRows</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">.</span>count<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> в <code class=\"gatsby-code-text\">useState</code>:</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\">Table</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\">// ✅ createRows() будет вызван только один раз</span>\n  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>rows<span class=\"token punctuation\">,</span> setRows<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</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\">createRows</span><span class=\"token punctuation\">(</span>props<span class=\"token punctuation\">.</span>count<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>React вызовет эту функцию один раз во время первого рендера. Смотрите <a href=\"/docs/hooks-reference.html#usestate\">справочник API по хуку <code class=\"gatsby-code-text\">useState</code></a>.</p>\n<p><strong>Иногда, вы захотите избежать повторных вызовов хука <code class=\"gatsby-code-text\">useRef()</code>.</strong> Например, возможно вы захотите убедиться, что экземпляр некоторого императивного класса создаётся только один раз:</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\">Image</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\">// ⚠️ IntersectionObserver создаётся на каждом рендере</span>\n  <span class=\"token keyword\">const</span> ref <span class=\"token operator\">=</span> <span class=\"token function\">useRef</span><span class=\"token punctuation\">(</span><span class=\"token keyword\">new</span> <span class=\"token class-name\">IntersectionObserver</span><span class=\"token punctuation\">(</span>onIntersect<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>У хука <code class=\"gatsby-code-text\">useRef</code> <strong>нет</strong> реализации, принимающей специальную функцию, как у <code class=\"gatsby-code-text\">useState</code>. Вместо этого, вы можете написать свою функцию, которая будет лениво создавать и назначать этот экземпляр:</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\">Image</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> ref <span class=\"token operator\">=</span> <span class=\"token function\">useRef</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=\"token comment\">// ✅ IntersectionObserver лениво создаётся только один раз</span>\n  <span class=\"token keyword\">function</span> <span class=\"token function\">getObserver</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>ref<span class=\"token punctuation\">.</span>current <span class=\"token operator\">===</span> <span class=\"token keyword\">null</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      ref<span class=\"token punctuation\">.</span>current <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">IntersectionObserver</span><span class=\"token punctuation\">(</span>onIntersect<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">return</span> ref<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token comment\">// Когда он вам понадобится, вызовите getObserver()</span>\n  <span class=\"token comment\">// ...</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Этот подход позволяет избежать создания больших объектов на всех этапах, кроме первого рендера, когда это действительно необходимо. Если вы используете Flow или TypeScript, вы можете также установить для <code class=\"gatsby-code-text\">getObserver()</code> непустой тип для уверенности.</p>\n<h3 id=\"are-hooks-slow-because-of-creating-functions-in-render\"><a href=\"#are-hooks-slow-because-of-creating-functions-in-render\" 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>Также учитывайте, что реализация хуков более эффективна по нескольким причинам:</p>\n<ul>\n<li>Хуки не требуют больших затрат, которые неизбежны в классах. Например, создание экземпляра класса и связывание обработчиков событий в конструкторе.</li>\n<li><strong>Проект, полностью написанный на хуках, имеет менее глубокое дерево компонентов</strong>. В случае использования рендер-пропсов, компонентов высшего порядка или контекста, финальное дерево компонентов было бы в несколько раз больше. Тут стоит понимать, что чем меньше дерево компонентов, тем меньше работы React должен делать.</li>\n</ul>\n<p>Традиционно, проблемы с оптимизацией встроенных функций в React связаны с тем, как передача новых колбэков на каждом рендере ломает оптимизации <code class=\"gatsby-code-text\">shouldComponentUpdate</code> в дочерних компонентах. Подход с хуками может решить эту проблему тремя способами.</p>\n<ul>\n<li>\n<p>Хук <a href=\"/docs/hooks-reference.html#usecallback\"><code class=\"gatsby-code-text\">useCallback</code></a> позволяет сохранять ту же самую ссылку на колбэк между повторными рендерами, поэтому <code class=\"gatsby-code-text\">shouldComponentUpdate</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 comment\">// Не создастся заново, пока `a` или `b` не изменятся</span>\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">const</span> memoizedCallback <span class=\"token operator\">=</span> <span class=\"token function\">useCallback</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 function\">doSomething</span><span class=\"token punctuation\">(</span>a<span class=\"token punctuation\">,</span> b<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>a<span class=\"token punctuation\">,</span> b<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></code></pre></div>\n</li>\n<li>Хук <a href=\"/docs/hooks-faq.html#how-to-memoize-calculations\"><code class=\"gatsby-code-text\">useMemo</code></a> облегчает контроль, когда конкретный дочерний компонент должен обновляться, уменьшая нужду в использовании чистых компонентов.</li>\n<li>Наконец, хук <a href=\"/docs/hooks-reference.html#usereducer\"><code class=\"gatsby-code-text\">useReducer</code></a> уменьшает необходимость передавать колбэки глубоко вниз по дереву, как описано ниже.</li>\n</ul>\n<h3 id=\"how-to-avoid-passing-callbacks-down\"><a href=\"#how-to-avoid-passing-callbacks-down\" 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\">dispatch</code> из хука <a href=\"/docs/hooks-reference.html#usereducer\"><code class=\"gatsby-code-text\">useReducer</code></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\">const</span> TodosDispatch <span class=\"token operator\">=</span> React<span class=\"token punctuation\">.</span><span class=\"token function\">createContext</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=\"token keyword\">function</span> <span class=\"token function\">TodosApp</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 comment\">// Примечание: `dispatch` не изменится во время повторных рендеров</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> <span class=\"token punctuation\">[</span>todos<span class=\"token punctuation\">,</span> dispatch<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useReducer</span><span class=\"token punctuation\">(</span>todosReducer<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><span class=\"token class-name\">TodosDispatch.Provider</span></span> <span class=\"token attr-name\">value</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>dispatch<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><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">DeepTree</span></span> <span class=\"token attr-name\">todos</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>todos<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><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span><span class=\"token class-name\">TodosDispatch.Provider</span></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>Любой дочерний компонент в дереве внутри <code class=\"gatsby-code-text\">TodosApp</code> может использовать функцию <code class=\"gatsby-code-text\">dispatch</code>, чтобы передать объекты-действия в <code class=\"gatsby-code-text\">TodosApp</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\">function</span> <span class=\"token function\">DeepChild</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=\"gatsby-highlight-code-line\">  <span class=\"token comment\">// Если мы хотим выполнить действие, мы можем получить dispatch из контекста.</span></span><span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> dispatch <span class=\"token operator\">=</span> <span class=\"token function\">useContext</span><span class=\"token punctuation\">(</span>TodosDispatch<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span></span>\n  <span class=\"token keyword\">function</span> <span class=\"token function\">handleClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token function\">dispatch</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span> type<span class=\"token operator\">:</span> <span class=\"token string\">'add'</span><span class=\"token punctuation\">,</span> text<span class=\"token operator\">:</span> <span class=\"token string\">'Привет'</span> <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\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>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>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>\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\">dispatch</code> по такому принципу — это рекомендуемый подход для вызова колбэков и избежания нежелательных обновлений в глубине дерева компонентов.</p>\n<p>Обратите внимание, что вы также можете передавать <em>состояние</em> приложения вниз через пропсы (более явно) или через контекст (более удобно для глубокого дерева). Если ваш контекст в том числе передаёт некое состояние, используйте два разных типа контекста. Так как контекст <code class=\"gatsby-code-text\">dispatch</code> никогда не изменяется, то компоненты, использующие его, не будут нуждаться в повторном рендере, если только им не требуется ещё и контекст с состоянием приложения.</p>\n<h3 id=\"how-to-read-an-often-changing-value-from-usecallback\"><a href=\"#how-to-read-an-often-changing-value-from-usecallback\" 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>Как получить часто изменяемое значение из хука <code class=\"gatsby-code-text\">useCallback</code>? </h3>\n<blockquote>\n<p>Примечание</p>\n<p>Мы рекомендуем <a href=\"#how-to-avoid-passing-callbacks-down\">передавать <code class=\"gatsby-code-text\">dispatch</code> вниз через контекст</a> вместо передачи отдельных колбэков через пропсы. Следующий подход приведён тут только для полноты картины в качестве лазейки.</p>\n<p>Также обратите внимание, что этот подход может вызвать проблемы в <a href=\"/blog/2018/03/27/update-on-async-rendering.html\">параллельном режиме</a>. Мы планируем предоставить более удобные альтернативы в будущем, но самый безопасный вариант сейчас — всегда отменять колбэк, если значение, на которое он опирается, поменялось.</p>\n</blockquote>\n<p>В некоторых редких случаях, вам может понадобиться закешировать колбэк с помощью хука <a href=\"/docs/hooks-reference.html#usecallback\"><code class=\"gatsby-code-text\">useCallback</code></a>, но кеширование не будет работать хорошо, потому что внутренняя функция будет пересоздаваться слишком часто. Если функция, которую вы кешируете, является обработчиком событий и не используется во время рендера, вы можете использовать <a href=\"#is-there-something-like-instance-variables\">реф в качестве свойства экземпляра</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\">Form</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>text<span class=\"token punctuation\">,</span> updateText<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token string\">''</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token keyword\">const</span> textRef <span class=\"token operator\">=</span> <span class=\"token function\">useRef</span><span class=\"token punctuation\">(</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<span class=\"gatsby-highlight-code-line\">    textRef<span class=\"token punctuation\">.</span>current <span class=\"token operator\">=</span> text<span class=\"token punctuation\">;</span> <span class=\"token comment\">// Записать это в реф</span></span>  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">const</span> handleSubmit <span class=\"token operator\">=</span> <span class=\"token function\">useCallback</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=\"gatsby-highlight-code-line\">    <span class=\"token keyword\">const</span> currentText <span class=\"token operator\">=</span> textRef<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">;</span> <span class=\"token comment\">// Прочитать из рефа</span></span>    <span class=\"token function\">alert</span><span class=\"token punctuation\">(</span>currentText<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>textRef<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span> <span class=\"token comment\">// Избегаем повторных созданий handleSubmit</span>\n\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></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>input</span> <span class=\"token attr-name\">value</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>text<span class=\"token punctuation\">}</span></span> <span class=\"token attr-name\">onChange</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token parameter\">e</span> <span class=\"token operator\">=></span> <span class=\"token function\">updateText</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">.</span>value<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><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">ExpensiveTree</span></span> <span class=\"token attr-name\">onSubmit</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>handleSubmit<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><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span></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>Это довольно запутанный подход, но он показывает, что вы можете сделать эту хитрую оптимизацию, если это вам действительно необходимо. В любом случае, советуем вынести эту логику в отдельный хук:</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\">Form</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>text<span class=\"token punctuation\">,</span> updateText<span class=\"token punctuation\">]</span> <span class=\"token operator\">=</span> <span class=\"token function\">useState</span><span class=\"token punctuation\">(</span><span class=\"token string\">''</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token comment\">// Будет закешировано, даже если значение `text` изменится:</span>\n<span class=\"gatsby-highlight-code-line\">  <span class=\"token keyword\">const</span> handleSubmit <span class=\"token operator\">=</span> <span class=\"token function\">useEventCallback</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 function\">alert</span><span class=\"token punctuation\">(</span>text<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>text<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\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></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>input</span> <span class=\"token attr-name\">value</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>text<span class=\"token punctuation\">}</span></span> <span class=\"token attr-name\">onChange</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span><span class=\"token parameter\">e</span> <span class=\"token operator\">=></span> <span class=\"token function\">updateText</span><span class=\"token punctuation\">(</span>e<span class=\"token punctuation\">.</span>target<span class=\"token punctuation\">.</span>value<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><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;</span><span class=\"token class-name\">ExpensiveTree</span></span> <span class=\"token attr-name\">onSubmit</span><span class=\"token script language-javascript\"><span class=\"token script-punctuation punctuation\">=</span><span class=\"token punctuation\">{</span>handleSubmit<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><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;/</span></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\n<span class=\"gatsby-highlight-code-line\"><span class=\"token keyword\">function</span> <span class=\"token function\">useEventCallback</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">fn<span class=\"token punctuation\">,</span> dependencies</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span></span>  <span class=\"token keyword\">const</span> ref <span class=\"token operator\">=</span> <span class=\"token function\">useRef</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\">throw</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Error</span><span class=\"token punctuation\">(</span><span class=\"token string\">'Невозможно вызвать обработчик события во время рендера.'</span><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\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    ref<span class=\"token punctuation\">.</span>current <span class=\"token operator\">=</span> fn<span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">[</span>fn<span class=\"token punctuation\">,</span> <span class=\"token operator\">...</span>dependencies<span class=\"token punctuation\">]</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n  <span class=\"token keyword\">return</span> <span class=\"token function\">useCallback</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\">const</span> fn <span class=\"token operator\">=</span> ref<span class=\"token punctuation\">.</span>current<span class=\"token punctuation\">;</span>\n    <span class=\"token keyword\">return</span> <span class=\"token function\">fn</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 punctuation\">,</span> <span class=\"token punctuation\">[</span>ref<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>В любом случае мы <strong>не советуем использовать этот подход</strong> и показываем его тут только для полноты картины. Вместо этого, старайтесь <a href=\"#how-to-avoid-passing-callbacks-down\">избегать передачи колбэков глубоко вниз в дерево</a>.</p>\n<h2 id=\"under-the-hood\"><a href=\"#under-the-hood\" 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<h3 id=\"how-does-react-associate-hook-calls-with-components\"><a href=\"#how-does-react-associate-hook-calls-with-components\" 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 связывает вызовы хуков с компонентом? </h3>\n<p>React следит за тем, какой компонент рендерится в данный момент. Благодаря <a href=\"/docs/hooks-rules.html\">правилам хуков</a>, мы знаем, что хуки вызываются только из React-компонентов (пользовательские хуки также вызываются только из React-компонентов).</p>\n<p>Существует внутренний список <code class=\"gatsby-code-text\">ячеек памяти</code>, связанных с каждым компонентом. Они являются JavaScript-объектами, в которых мы можем хранить некоторые данные. Когда вызывается некий хук, например <code class=\"gatsby-code-text\">useState()</code>, он читает значение текущей ячейки (или инициализирует её во время первого рендера) и двигает указатель на следующую. Таким способом каждый вызов <code class=\"gatsby-code-text\">useState()</code> получит своё независимое состояние.</p>\n<h3 id=\"what-is-the-prior-art-for-hooks\"><a href=\"#what-is-the-prior-art-for-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<ul>\n<li>Наши старые эксперименты с функциональным API в репозитории <a href=\"https://github.com/reactjs/react-future/tree/master/07%20-%20Returning%20State\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">react-future</a>.</li>\n<li>Эксперименты с API рендер-пропс от React-сообщества, включая <a href=\"https://github.com/reactions/component\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">компонент Reactions</a> от <a href=\"https://github.com/ryanflorence\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Райна Флоренса (Ryan Florence)</a>.</li>\n<li><a href=\"https://github.com/trueadm\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Dominic Gannaway</a> и его предложение <a href=\"https://gist.github.com/trueadm/17beb64288e30192f3aa29cad0218067\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">ключевого слова <code class=\"gatsby-code-text\">adopt</code></a>, в качестве синтаксического сахара для паттерна рендер-пропс.</li>\n<li>Переменные и ячейки состояния в <a href=\"http://displayscript.org/introduction.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">DisplayScript</a>.</li>\n<li><a href=\"https://reasonml.github.io/reason-react/docs/en/state-actions-reducer.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Компоненты-редюсеры</a> в ReasonReact.</li>\n<li><a href=\"http://reactivex.io/rxjs/class/es6/Subscription.js~Subscription.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Подписки</a> в Rx.</li>\n<li><a href=\"https://github.com/ocamllabs/ocaml-effects-tutorial#2-effectful-computations-in-a-pure-setting\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Алгебраические эффекты</a> в Multicore OCaml.</li>\n</ul>\n<p><a href=\"https://github.com/sebmarkbage\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Себастьян Маркбаге (Sebastian Markbåge)</a> предложил изначальный дизайн хуков, который позднее улучшили <a href=\"https://github.com/acdlite\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Эндрю Кларк (Andrew Clark)</a>, <a href=\"https://github.com/sophiebits\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Софи Алперт (Sophie Alpert)</a>, <a href=\"https://github.com/trueadm\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Доминик Ганнауэй (Dominic Gannaway)</a> и другие участники команды React.</p>","frontmatter":{"title":"Хуки: ответы на вопросы","next":null,"prev":"hooks-reference.html"},"fields":{"path":"content/docs/hooks-faq.md","slug":"docs/hooks-faq.html"}}},"pageContext":{"slug":"docs/hooks-faq.html"}},"staticQueryHashes":[]}