{"id":311306,"date":"2020-10-12T09:00:24","date_gmt":"2020-10-12T09:00:24","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=311306"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=311306","title":{"rendered":"\u041a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0435 \u0445\u0443\u043a\u0438. Part 1"},"content":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/523034\/\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/sj\/uf\/xu\/sjufxuqiadew2_zg3veuhlac7em.png\"><\/p>\n<p>  \u0414\u043e\u0431\u0440\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0443\u0442\u043e\u043a, \u0434\u0440\u0443\u0437\u044c\u044f!<\/p>\n<p>  \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044e \u043f\u0435\u0440\u0432\u0443\u044e \u0434\u0435\u0441\u044f\u0442\u043a\u0443 <a href=\"https:\/\/usehooks.com\/\" rel=\"nofollow\">\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0445\u0443\u043a\u043e\u0432<\/a>.<\/p>\n<p>  \u041e\u0433\u043b\u0430\u0432\u043b\u0435\u043d\u0438\u0435<\/p>\n<ul>\n<li><a href=\"#useMemoCompare\">useMemoCompare<\/a><\/li>\n<li><a href=\"#useAsync\">useAsync<\/a><\/li>\n<li><a href=\"#useRequireAuth\">useRequireAuth<\/a><\/li>\n<li><a href=\"#useRouter\">useRouter<\/a><\/li>\n<li><a href=\"#useAuth\">useAuth<\/a><\/li>\n<li><a href=\"#useEventListener\">useEventListener<\/a><\/li>\n<li><a href=\"#useWhyDidYouUpdate\">useWhyDidYouUpdate<\/a><\/li>\n<li><a href=\"#useDarkMode\">useDarkMode<\/a><\/li>\n<li><a href=\"#useMedia\">useMedia<\/a><\/li>\n<li><a href=\"#useLocalStorage\">useLocalStorage<\/a><\/li>\n<\/ul>\n<p>  <a name=\"habracut\"><\/a><br \/>  <a name=\"useMemoCompare\"><\/a><\/p>\n<h3>useMemoCompare<\/h3>\n<p>  \u0414\u0430\u043d\u043d\u044b\u0439 \u0445\u0443\u043a \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 useMemo, \u043d\u043e \u0432\u043c\u0435\u0441\u0442\u043e \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0435\u043c\u0443 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u044e\u0449\u0430\u044f \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0435 \u0438 \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f. \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0442\u044c \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430, \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043c\u0435\u0442\u043e\u0434\u044b \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0438\u043b\u0438 \u0434\u0435\u043b\u0430\u0442\u044c \u0447\u0442\u043e-\u0442\u043e \u0435\u0449\u0435 \u0432 \u0446\u0435\u043b\u044f\u0445 \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f. \u0415\u0441\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 true, \u0445\u0443\u043a \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0441\u0442\u0430\u0440\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442. \u0421\u0442\u043e\u0438\u0442 \u043e\u0442\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u044d\u0442\u043e\u0442 \u0445\u0443\u043a, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 useMemo, \u043d\u0435 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0435\u0442 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u044b\u0445 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439. \u0415\u043c\u0443 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044f. \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u043a\u043e\u0433\u0434\u0430 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 \u0441 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c\u0438, \u0438 \u043d\u0435 \u0445\u043e\u0442\u0438\u0442\u0435 \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u0445 \u0437\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u043f\u0435\u0440\u0435\u0434 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u043e\u0439. \u0415\u0441\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u0435\u043b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 (\u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u043f\u0440\u043e\u043f\u0441\u043e\u0432), \u0442\u043e\u0433\u0434\u0430 \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u043d\u043e\u0432\u044b\u043c \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0435. \u0415\u0441\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c\u044e useEffect, \u0442\u043e\u0433\u0434\u0430 \u044d\u0444\u0444\u0435\u043a\u0442 \u0431\u0443\u0434\u0435\u0442 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0435, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0432\u0435\u0441\u0442\u0438 \u043a \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c, \u0432\u043f\u043b\u043e\u0442\u044c \u0434\u043e \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430. \u0414\u0430\u043d\u043d\u044b\u0439 \u0445\u0443\u043a \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0433\u043e \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0441\u0442\u0430\u0440\u0443\u044e \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432\u043c\u0435\u0441\u0442\u043e \u043d\u043e\u0432\u043e\u0439, \u0435\u0441\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0440\u0438\u0437\u043d\u0430\u043b\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u043c\u0438.<\/p>\n<pre><code class=\"javascript\">import React, { useState, useEffect, useRef } from &quot;react&quot;;  \/\/ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 function MyComponent({ obj }) {   const [state, setState] = useState();    \/\/ \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0441\u0442\u0430\u0440\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442, \u0435\u0441\u043b\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e &quot;id&quot; \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u043e\u0441\u044c   const objFinal = useMemoCompare(obj, (prev, next) =&gt; {     return prev &amp;&amp; prev.id === next.id;   });    \/\/ \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u044d\u0444\u0444\u0435\u043a\u0442 \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 objFinal   \/\/ \u0435\u0441\u043b\u0438 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c obj \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e, \u0431\u0435\u0437 \u043d\u0430\u0448\u0435\u0433\u043e \u0445\u0443\u043a\u0430, \u0438 obj \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438 \u0431\u0443\u0434\u0435\u0442   \/\/ \u043d\u043e\u0432\u044b\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0435, \u0442\u043e\u0433\u0434\u0430 \u044d\u0444\u0444\u0435\u043a\u0442 \u0442\u0430\u043a\u0436\u0435 \u0431\u0443\u0434\u0435\u0442 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0435   \/\/ \u0447\u0442\u043e \u0435\u0449\u0435 \u0445\u0443\u0436\u0435, \u0435\u0441\u043b\u0438 \u043d\u0430\u0448 \u044d\u0444\u0444\u0435\u043a\u0442 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f, \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043a\u043e\u043d\u0447\u0438\u0442\u044c\u0441\u044f \u0431\u0435\u0441\u043a\u043e\u043d\u0435\u0447\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c   \/\/ \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u044d\u0444\u0444\u0435\u043a\u0442 -&gt; \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0432\u043b\u0435\u0447\u0435\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u044b\u0439 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433 -&gt; \u0441\u043d\u043e\u0432\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u044d\u0444\u0444\u0435\u043a\u0442 -&gt; \u0438 \u0442.\u0434.   useEffect(() =&gt; {     \/\/ \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0438 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u0435\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e     return objFinal.someMethod().then((value) =&gt; setState(value));   }, [objFinal]);    \/\/ \u043f\u043e\u0447\u0435\u043c\u0443 \u043d\u0430\u043c \u043d\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c [obj.id] \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438?   useEffect(() =&gt; {     \/\/ eslint-plugin-hooks \u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e \u0440\u0435\u0448\u0438\u0442, \u0447\u0442\u043e obj \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439     \/\/ \u0438 \u043d\u0430\u043c \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c eslint-disable-next-line \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b     \/\/ \u043b\u0443\u0447\u0448\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0441\u0442\u0430\u0440\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0430\u0448\u0435\u0433\u043e \u0445\u0443\u043a\u0430     return obj.someMethod().then((value) =&gt; setState(value));   }, [obj.id]); }  \/\/ \u0445\u0443\u043a function useMemoCompare(next, compare) {   \/\/ ref \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f   const prevRef = useRef();   const prev = prevRef.current;    \/\/ \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0435 \u0438 \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u044e   \/\/ \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u0438\u0445 \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u043e\u0441\u0442\u0438   const isEqual = compare(prev, next);    \/\/ \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0435 \u0440\u0430\u0432\u043d\u044b, \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c prevRef   \/\/ \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435\u0440\u0430\u0432\u0435\u043d\u0441\u0442\u0432\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439   \/\/ \u043f\u043e\u044d\u0442\u043e\u043c\u0443, \u0435\u0441\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u0435\u0440\u043d\u0443\u043b\u0430 true, \u0445\u0443\u043a \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0430\u0440\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435   useEffect(() =&gt; {     if (!isEqual) {       prevRef.current = next;     }   });    \/\/ \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0432\u043d\u044b, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0441\u0442\u0430\u0440\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435   return isEqual ? prev : next; } <\/code><\/pre>\n<p>  <a name=\"useAsync\"><\/a><\/p>\n<h3>useAsync<\/h3>\n<p>  \u0425\u043e\u0440\u043e\u0448\u0435\u0439 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u043e\u0439 \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u0443\u0441\u0430 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u041f\u0440\u0438\u043c\u0435\u0440\u043e\u043c<br \/>  \u043c\u043e\u0436\u0435\u0442 \u0441\u043b\u0443\u0436\u0438\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 API \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u0435\u0440\u0435\u0434 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u043e\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u043e\u0432. \u0414\u0440\u0443\u0433\u0438\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043a\u043d\u043e\u043f\u043a\u0438 \u043d\u0430 \u0432\u0440\u0435\u043c\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0444\u043e\u0440\u043c\u044b \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430. \u0412\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0433\u0440\u044f\u0437\u043d\u044f\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0432\u044b\u0437\u043e\u0432\u043e\u0432 useState \u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0439 \u0445\u0443\u043a, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u044e\u0449\u0438\u0439 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0438\u0439 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u00abvalue\u00bb, \u00aberror\u00bb \u0438 \u00abstatus\u00bb, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u00abstatus\u00bb \u044f\u0432\u043b\u044f\u044e\u0442\u0441\u044f \u00abidle\u00bb, \u00abpending\u00bb, \u00absuccess\u00bb \u0438 \u00aberror\u00bb. \u041d\u0430\u0448 \u0445\u0443\u043a \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043a\u0430\u043a \u0441\u0440\u0430\u0437\u0443, \u0442\u0430\u043a \u0438 \u0441 \u0437\u0430\u0434\u0435\u0436\u043a\u043e\u0439 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u00abexecute\u00bb.<\/p>\n<pre><code class=\"javascript\">import React, { useState, useEffect, useCallback } from 'react'  \/\/ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 function App() {   const {execute, status, value, error } = useAsync(myFunction, false)    return (     &lt;div&gt;       {status === 'idle' &amp;&amp; &lt;div&gt;\u041d\u0430\u0447\u043d\u0438\u0442\u0435 \u0432\u0430\u0448\u0435 \u043f\u0443\u0442\u0435\u0448\u0435\u0441\u0442\u0432\u0438\u0435 \u0441 \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043d\u043e\u043f\u043a\u0438&lt;\/div&gt;}       {status === 'success' &amp;&amp; &lt;div&gt;{value}&lt;\/div&gt;}       {status === 'error' &amp;&amp; &lt;div&gt;{error}&lt;\/div&gt;}       &lt;button onClick={execute} disabled={status === 'pending'}&gt;         {status !== 'pending' ? '\u041d\u0430\u0436\u043c\u0438 \u043c\u0435\u043d\u044f' : '\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430...'}       &lt;\/button&gt;     &lt;\/div&gt;   ) }  \/\/ \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0445\u0443\u043a\u0430 \/\/ \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 50% \u0441\u043b\u0443\u0447\u0430\u0435\u0432 const myFunction = () =&gt; {   return new Promise((resolve, reject) =&gt; {     setTimeout(() =&gt; {       const random = Math.random() * 10       random &lt;=5         ? resolve('\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u043e')         : reject('\u041f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430')     }, 2000)   }) }  \/\/ \u0445\u0443\u043a const useAsync = (asyncFunction, immediate = true) =&gt; {   const [status, setStatus] = useState('idle')   const [value, setValue] = useState(null)   const [error, setError] = useState(null)    \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f &quot;execute&quot; \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u0442 asyncFunction \u0438   \/\/ \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0439 \u0434\u043b\u044f pending, value \u0438 error   \/\/ useCallback \u043f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0432\u044b\u0437\u043e\u0432 useEffect \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0435   \/\/ useEffect \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 asyncFunction   const execute = useCallback(() =&gt; {     setStatus('pending')     setValue(null)     setError(null)      return asyncFunction()       .then(response =&gt; {         setValue(response)         setStatus('success')       })       .catch(error =&gt; {         setError(error)         setStatus('error')       })   }, [asyncFunction])    \/\/ \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c execute \u0434\u043b\u044f \u043d\u0435\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f   \/\/ \u0441 \u0434\u0440\u0443\u0433\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, execute \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0432\u044b\u0437\u0432\u0430\u043d\u0430 \u043f\u043e\u0437\u0436\u0435   \/\/ \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u0430\u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043d\u0430\u0436\u0430\u0442\u0438\u044f \u043a\u043d\u043e\u043f\u043a\u0438   useEffect(() =&gt; {     if (immediate) {       execute()     }   }, [execute, immediate])    return { execute, status, value, error } } <\/code><\/pre>\n<p>  <a name=\"useRequireAuth\"><\/a><\/p>\n<h3>useRequireAuth<\/h3>\n<p>  \u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0434\u0430\u043d\u043d\u043e\u0433\u043e \u0445\u0443\u043a\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0440\u0438 \u0432\u044b\u0445\u043e\u0434\u0435 \u0438\u0437 \u0443\u0447\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438. \u041d\u0430\u0448 \u0445\u0443\u043a \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0445\u0443\u043a\u043e\u0432 \u00abuseAuth\u00bb \u0438 \u00abuseRouter\u00bb. \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0444\u0443\u043a\u043d\u0446\u0438\u043e\u043d\u0430\u043b \u0432 \u0445\u0443\u043a\u0435 \u00abuseAuth\u00bb, \u043d\u043e \u0442\u043e\u0433\u0434\u0430 \u043d\u0430\u043c \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0432\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0435\u0433\u043e \u0441 \u0441\u0445\u0435\u043c\u0443 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0430\u0446\u0438\u0438. \u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u0443 useAuth \u0438 useRouter, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0432 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u0430\u0441\u0442\u043e\u043c\u043d\u043e\u0433\u043e \u0445\u0443\u043a\u0430.<\/p>\n<pre><code class=\"javascript\">import Dashboard from &quot;.\/Dahsboard.js&quot;; import Loading from &quot;.\/Loading.js&quot;; import { useRequireAuth } from &quot;.\/use-require-auth.js&quot;;  function DashboardPage(props) {   const auth = useRequireAuth();    \/\/ \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c auth \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f null (\u0434\u0430\u043d\u043d\u044b\u0435 \u0435\u0449\u0435 \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u044b)   \/\/ \u0438\u043b\u0438 false (\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u044b\u0448\u0435\u043b \u0438\u0437 \u0443\u0447\u0435\u0442\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438)   \/\/ \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0438\u043d\u0434\u0438\u043a\u0430\u0442\u043e\u0440 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438   if (!auth) {     return &lt;Loading \/&gt;;   }    return &lt;Dashboard auth={auth} \/&gt;; }  \/\/ \u0445\u0443\u043a (use-require-auth.js) import { useEffect } from &quot;react&quot;; import { useAuth } from &quot;.\/use-auth.js&quot;; import { useRouter } from &quot;.\/use-router.js&quot;;  function useRequireAuth(redirectUrl = &quot;.\/signup&quot;) {   const auth = useAuth();   const router = useRouter();    \/\/ \u0435\u0441\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c auth.user \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f false,   \/\/ \u0437\u043d\u0430\u0447\u0438\u0442, \u0432\u0445\u043e\u0434 \u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d, \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435   useEffect(() =&gt; {     if (auth.user === false) {       router.push(redirectUrl);     }   }, [auth, router]);    return auth; } <\/code><\/pre>\n<p>  <a name=\"useRouter\"><\/a><\/p>\n<h3>useRouter<\/h3>\n<p>  \u0415\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u0432 \u0441\u0432\u043e\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u0435 React Router, \u0442\u043e \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c, \u0447\u0442\u043e \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u043f\u043e\u044f\u0432\u0438\u043b\u043e\u0441\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0445\u0443\u043a\u043e\u0432, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a \u00abuseParams\u00bb, \u00abuseLocation\u00bb, \u00abuseHistory\u00bb \u0438 \u00abuseRouterMatch\u00bb. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u0438\u0445 \u0432 \u043e\u0434\u0438\u043d \u0445\u0443\u043a, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0438\u0439 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 \u043c\u0435\u0442\u043e\u0434\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u044b. \u041c\u044b \u043f\u043e\u043a\u0430\u0436\u0435\u043c, \u043a\u0430\u043a \u0441\u043a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0445\u0443\u043a\u043e\u0432 \u0438 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043e\u0434\u0438\u043d \u043e\u0431\u044a\u0435\u043a\u0442, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0439 \u0438\u0445 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u0414\u043b\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a \u0432\u0440\u043e\u0434\u0435 React Router \u0438\u043c\u0435\u0435\u0442 \u0441\u043c\u044b\u0441\u043b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0432\u044b\u0431\u043e\u0440 \u043d\u0443\u0436\u043d\u043e\u0433\u043e \u0445\u0443\u043a\u0430. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u043d\u0435\u043d\u0443\u0436\u043d\u043e\u0433\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430. \u041d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u043d\u0430\u043c \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u0438\u043b\u0438 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u043d\u044b\u0445 \u0445\u0443\u043a\u043e\u0432.<\/p>\n<pre><code class=\"javascript\">import { useMemo } from &quot;react&quot;; import {   useParams,   useLocation,   useHistory,   useRouterMatch, } from &quot;react-router-dom&quot;; import queryString from &quot;query-string&quot;;  \/\/ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 function MyComponent() {   \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 \u0440\u043e\u0443\u0442\u0435\u0440\u0430   const router = useRouter();    \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 (?postId=123) \u0438\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 (\/:postId)   console.log(router.query.postId);    \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u0443\u0442\u0438   console.log(router.pathname);    \/\/ \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043d\u0430\u0432\u0438\u0433\u0430\u0446\u0438\u044e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e router.push()   return &lt;button onClick={(e) =&gt; router.push(&quot;.\/about&quot;)}&gt;About&lt;\/button&gt;; }  \/\/ \u0445\u0443\u043a export function useRouter() {   const params = useParams();   const location = useLocation();   const history = useHistory();   const match = useRouterMatch();    \/\/ \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043d\u0430\u0448 \u043e\u0431\u044a\u0435\u043a\u0442 \u0440\u043e\u0443\u0442\u0435\u0440\u0430   \/\/ \u0437\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u043c \u0435\u0433\u043e \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u043b\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439   return useMemo(() =&gt; {     return {       \/\/ \u0434\u043b\u044f \u0443\u0434\u043e\u0431\u0441\u0442\u0432\u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c push(), replace() \u0438 pathname \u043d\u0430 \u0432\u0435\u0440\u0445\u043d\u0435\u043c \u0443\u0440\u043e\u0432\u043d\u0435       push: history.push,       replace: history.replace,       pathname: location.pathname,       \/\/ \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u0441\u0442\u0440\u043e\u043a\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 &quot;query&quot;       \/\/ \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u043e\u043d\u0438 \u0431\u044b\u043b\u0438 \u0432\u0437\u0430\u0438\u043c\u043e\u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u043c\u0438       \/\/ \u043f\u0440\u0438\u043c\u0435\u0440: \/:topic?sort=popular -&gt; { topic: 'react', sort: 'popular' }       query: {         ...queryString.parse(location.search), \/\/ \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u0441\u0442\u0440\u043e\u043a\u0443 \u0432 \u043e\u0431\u044a\u0435\u043a\u0442         ...params,       },       \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u044b &quot;match&quot;, &quot;location&quot; \u0438 &quot;history&quot;       \/\/ \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0433\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0430 React Router       match,       location,       history,     };   }, [params, match, location, history]); } <\/code><\/pre>\n<p>  <a name=\"useAuth\"><\/a><\/p>\n<h3>useAuth<\/h3>\n<p>  \u041e\u0431\u044b\u0447\u043d\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u044f\u0442\u0441\u044f \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0442\u043e\u0433\u043e, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b \u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u0445\u043e\u0434 \u0432 \u0443\u0447\u0435\u0442\u043d\u0443\u044e \u0437\u0430\u043f\u0438\u0441\u044c. \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0445 \u044d\u0442\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0442 \u043c\u0435\u0442\u043e\u0434\u044b \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a signin, signout, sendPasswordResetEmail \u0438 \u0442.\u0434. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0445\u0443\u043a \u00abuseAuth\u00bb, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u043a\u0443 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439. \u0412\u043c\u0435\u0441\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 useAuth \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u043d\u0430\u0448 \u0445\u0443\u043a \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 useContext \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430. \u041d\u0430\u0441\u0442\u043e\u044f\u0449\u0430\u044f \u043c\u0430\u0433\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0432 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435 \u00abProvideAuth\u00bb, \u0433\u0434\u0435 \u0432\u0441\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 (\u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043c\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c Firebase) \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u0445\u0443\u043a \u00abuseProvideAuth\u00bb. \u0417\u0430\u0442\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c, \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0438\u043c useAuth. \u0412 \u0441\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c \u0431\u0443\u0434\u0435\u0442 \u0431\u043e\u043b\u044c\u0448\u0435 \u0441\u043c\u044b\u0441\u043b\u0430 \u043f\u043e\u0441\u043b\u0435 \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u043b\u0435\u043d\u0438\u0435\u043c \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c. \u0415\u0449\u0435 \u043e\u0434\u043d\u043e\u0439 \u043f\u0440\u0438\u0447\u0438\u043d\u043e\u0439, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043c\u043d\u0435 \u043d\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u044d\u0442\u043e\u0442 \u0445\u0443\u043a, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 (Firebase), \u0447\u0442\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0430\u0435\u0442 \u0432\u043d\u0435\u0441\u0435\u043d\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.<\/p>\n<pre><code class=\"javascript\">\/\/ \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 App import React from &quot;react&quot;; import { ProvideAuth } from &quot;.\/use-auth.js&quot;;  function App(props) {   return (     &lt;ProvideAuth&gt;       {\/*         \u0437\u0434\u0435\u0441\u044c \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0440\u043e\u0443\u0442\u0435\u0440\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u0432\u0438\u0441\u044f\u0442 \u043e\u0442 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f         \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 Next.js, \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a: \/pages\/_app.js       *\/}     &lt;\/ProvideAuth&gt;   ); }  \/\/ \u043b\u044e\u0431\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 import React from &quot;react&quot;; import { useAuth } from &quot;.\/use-auth.js&quot;;  function NavBar(props) {   \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 auth \u0438 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u043a\u0443 \u043f\u0440\u0438 \u0435\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438   const auth = useAuth();    return (     &lt;NavbarContainer&gt;       &lt;Logo \/&gt;       &lt;Menu&gt;         &lt;Link to=&quot;\/about&quot;&gt;About&lt;\/Link&gt;         &lt;Link to=&quot;\/contact&quot;&gt;Contact&lt;\/Link&gt;         {auth.user ? (           &lt;Fragment&gt;             &lt;Link to=&quot;\/account&quot;&gt;Account ({auth.user.email})&lt;\/Link&gt;             &lt;Button onClick={() =&gt; auth.signout()}&gt;Signout&lt;\/Button&gt;           &lt;\/Fragment&gt;         ) : (           &lt;Link to=&quot;\/signin&quot;&gt;Signin&lt;\/Link&gt;         )}       &lt;\/Menu&gt;     &lt;\/NavbarContainer&gt;   ); }  \/\/ \u0445\u0443\u043a (use-auth.js) import React, { useState, useEffect, useContext, createContext } from &quot;react&quot;; import * as firebase from &quot;firebase\/app&quot;; import &quot;firebase\/auth&quot;;  \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f Firebase firebase.initializeApp({   apiKey: &quot;&quot;,   authDomain: &quot;&quot;,   projectId: &quot;&quot;,   appID: &quot;&quot;, });  const authContext = createContext();  \/\/ \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 Provider, \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u044e\u0449\u0438\u0439 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0434\u0435\u043b\u0430\u044e\u0449\u0438\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 &quot;auth&quot; \/\/ \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c \u0434\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e \u0434\u043e\u0447\u0435\u0440\u043d\u0435\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0435\u0433\u043e useAuth export const useAuth = () =&gt; {   return useContext(authContext); };  \/\/ \u0445\u0443\u043a \u0434\u043b\u044f \u0434\u043e\u0447\u0435\u0440\u043d\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u0430 &quot;auth&quot; \/\/ \u0438 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \u043f\u0440\u0438 \u0435\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 export const useAuth = () =&gt; {   return useContext(authContext); };  \/\/ \u0445\u0443\u043a \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440\u0430, \u0441\u043e\u0437\u0434\u0430\u044e\u0449\u0438\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 &quot;auth&quot; \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 function useProviderAuth() {   const [user, setUser] = useState(null);    \/\/ \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0435\u043c \u043b\u044e\u0431\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b Firebase, \u043d\u0435\u043e\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f   \/\/ \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f   const signin = (email, password) =&gt; {     return firebase       .auth()       .signInWithEmailAndPassword(email, password)       .then((response) =&gt; {         setUser(response.user);         return response.user;       });   };    const signup = (email, password) =&gt; {     return firebase       .auth()       .createUserWithEmailAndPassword(email, password)       .then((response) =&gt; {         setUser(response.user);         return response.user;       });   };    const signout = () =&gt; {     return firebase       .auth()       .signOut()       .then(() =&gt; {         setUser(false);       });   };    const sendPasswordResetEmail = (email) =&gt; {     return firebase       .auth()       .sendPasswordResetEmail(email)       .then(() =&gt; true);   };    const confirmPasswordReset = (code, password) =&gt; {     return firebase       .auth()       .confirmPasswordReset(code, password)       .then(() =&gt; true);   };    \/\/ \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u0440\u0438 \u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438   \/\/ \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0432 \u043a\u043e\u043b\u0431\u044d\u043a\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0442\u043e\u043c\u0443   \/\/ \u0447\u0442\u043e \u043b\u044e\u0431\u043e\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0439 \u0445\u0443\u043a   \/\/ \u043f\u0435\u0440\u0435\u0440\u0438\u0441\u043e\u0432\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 &quot;auth&quot;   useEffect(() =&gt; {     const unsubscribe = firebase.auth().onAuthStateChange((user) =&gt; {       if (user) {         setUser(user);       } else {         setUser(false);       }     });      \/\/ \u043e\u0442\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c\u0441\u044f \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f     return () =&gt; unsubscribe();   }, []);    \/\/ \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043e\u0431\u044a\u0435\u043a\u0442 &quot;user&quot; \u0438 \u043c\u0435\u0442\u043e\u0434\u044b \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438   return {     user,     signin,     signup,     signout,     sendPasswordResetEmail,     confirmPasswordReset,   }; } <\/code><\/pre>\n<p>  <a name=\"useEventListener\"><\/a><\/p>\n<h3>useEventListener<\/h3>\n<p>  \u0415\u0441\u043b\u0438 \u0432\u0430\u043c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u0438\u043c\u0435\u0442\u044c \u0434\u0435\u043b\u043e \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432 \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 useEffect, \u0443 \u0432\u0430\u0441 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u0436\u0435\u043b\u0430\u043d\u0438\u0435 \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0438\u0445 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0445\u0443\u043a. \u0412 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u043c \u043d\u0438\u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0445\u0443\u043a \u00abuseEventListener\u00bb, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u00abaddEventListener\u00bb, \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0438 \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u0438\u0445 \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435.  <\/p>\n<pre><code class=\"javascript\">import { useState, useRef, useEffect, useCallback } from &quot;react&quot;;  \/\/ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 function App() {   \/\/ \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u043a\u0443\u0440\u0441\u043e\u0440\u0430   const [coords, setCoords] = useState({ x: 0, y: 0 });    \/\/ \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043e\u0431\u0435\u0440\u043d\u0443\u0442 \u0432 useCallback,   \/\/ \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u0441\u044f   const handler = useCallback(     ({ clientX, clientY }) =&gt; {       \/\/ \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b       setCoords({ x: clientX, y: clientY });     },     [setCoords]   );    \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0430\u0448\u0435\u0433\u043e \u0445\u0443\u043a\u0430   useEventListener(&quot;mousemove&quot;, handler);    return &lt;h1&gt;\u041f\u043e\u0437\u0438\u0446\u0438\u044f \u043a\u0443\u0440\u0441\u043e\u0440\u0430: ({(coords.x, coords.y)})&lt;\/h1&gt;; }  \/\/ \u0445\u0443\u043a function useEventListener(eventName, handler, element = window) {   \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0443, \u0445\u0440\u0430\u043d\u044f\u0449\u0443\u044e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a   const saveHandler = useRef();    \/\/ \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c ref.current \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430   \/\/ \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043d\u0430\u0448\u0435\u043c\u0443 \u044d\u0444\u0444\u0435\u043a\u0442\u0443 \u0432\u0441\u0435\u0433\u0434\u0430 \u0438\u043c\u0435\u0442\u044c \u0434\u0435\u043b\u043e \u0441 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u043c   \/\/ \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0435\u043c\u0443 \u043c\u0430\u0441\u0441\u0438\u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439   \/\/ \u0447\u0442\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u044d\u0444\u0444\u0435\u043a\u0442 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0435   useEffect(() =&gt; {     saveHandler.current = handler;   }, [handler]);    useEffect(     () =&gt; {       \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 addEventListener       const isSupported = element &amp;&amp; element.addEventListener;       if (!isSupported) return;        \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a, \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0439 \u0432 ref       const eventListener = (event) =&gt; saveHandler.current(event);        \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u0439       element.addEventListener(eventName, eventListener);        \/\/ \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435       return () =&gt; {         element.removeEventListener(eventName, eventListener);       };     },     [eventName, element] \/\/ \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430   ); } <\/code><\/pre>\n<p>  <a name=\"useWhyDidYouUpdate\"><\/a><\/p>\n<h3>useWhyDidYouUpdate<\/h3>\n<p>  \u0414\u0430\u043d\u043d\u044b\u0439 \u0445\u0443\u043a \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c, \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043a\u0430\u043a\u0438\u0445 \u043f\u0440\u043e\u043f\u0441\u043e\u0432 \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442 \u043a \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u043c\u0443 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0443. \u0415\u0441\u043b\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u00ab\u0441\u043b\u043e\u0436\u043d\u043e\u0439\u00bb \u0438 \u0432\u044b \u0443\u0432\u0435\u0440\u0435\u043d\u044b, \u0447\u0442\u043e \u043e\u043d\u0430 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0447\u0438\u0441\u0442\u043e\u0439, \u0442.\u0435. \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0434\u043b\u044f \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0445 \u043f\u0440\u043e\u043f\u0441\u043e\u0432, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0432\u044b\u0441\u0448\u0435\u0433\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u00abReact.memo\u00bb, \u043a\u0430\u043a \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c \u0432 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043d\u0438\u0436\u0435. \u0415\u0441\u043b\u0438 \u043f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0438 \u043d\u0435 \u043f\u0440\u0435\u043a\u0440\u0430\u0442\u0438\u043b\u0438\u0441\u044c, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c useWhyDidYouUpdate, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c \u0438\u0437\u043c\u0435\u043d\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u043f\u0440\u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0435 \u043f\u0440\u043e\u043f\u0441\u044b \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439.<\/p>\n<pre><code class=\"javascript\">import { useState, useEffect, useRef } from &quot;react&quot;;  \/\/ \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c, \u0447\u0442\u043e &lt;Counter&gt; \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0434\u043e\u0440\u043e\u0433\u0438\u043c \u0434\u043b\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0433\u043e \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0430 \/\/ \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u043e\u0431\u0435\u0440\u043d\u0443\u043b\u0438 \u0435\u0433\u043e \u0432 React.memo, \u043d\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u043e\u0441\u0442\u0430\u043b\u0438\u0441\u044c \/\/ \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 useWhyDidYouUpdate \u0434\u043b\u044f \u043f\u0440\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438 const Counter = React.memo((props) =&gt; {   useWhyDidYouUpdate(&quot;Counter&quot;, props);   return &lt;div style={props.style}&gt;{props.count}&lt;\/div&gt;; });  function App() {   const [count, setCount] = useState(0);   const [userId, setUserId] = useState(0);    \/\/ \u0445\u0443\u043a \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442, \u0447\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442, \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0439 \u0434\u043b\u044f \u0441\u0442\u0438\u043b\u0438\u0437\u0430\u0446\u0438\u0438 &lt;Counter&gt;   \/\/ \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0435, \u0434\u0430\u0436\u0435 \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u043c\u0435\u043d\u044f\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 userId   \/\/ \u043d\u0430\u0436\u0438\u043c\u0430\u044f \u043a\u043d\u043e\u043f\u043a\u0443 &quot;switch user&quot;. \u0420\u0430\u0437\u0443\u043c\u0435\u0435\u0442\u0441\u044f, \u044d\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u043e\u0442\u043e\u043c\u0443   \/\/ \u0447\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442 \u0437\u0430\u043d\u043e\u0432\u043e \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043d\u0433\u0435   \/\/ \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0445\u0443\u043a\u0443 \u043c\u044b \u043f\u043e\u043d\u044f\u043b\u0438, \u0447\u0442\u043e \u043d\u0430\u043c \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u043e\u0431\u044a\u0435\u043a\u0442   \/\/ \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u043c\u0438 \u0442\u0435\u043b\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430   const counterStyle = {     fontSize: &quot;3rem&quot;,     color: &quot;red&quot;,   }; }  return (   &lt;div&gt;     &lt;div className=&quot;counter&quot;&gt;       &lt;Counter count={count} style={counterStyle} \/&gt;       &lt;button onClick={() =&gt; setCount(count + 1)}&gt;Increment&lt;\/button&gt;     &lt;\/div&gt;     &lt;div className=&quot;user&quot;&gt;       &lt;img src={`http:\/\/i.pravatar.cc\/80?img=${userId}`} \/&gt;       &lt;button onClick={() =&gt; setUserId(userId + 1)}&gt;Switch User&lt;\/button&gt;     &lt;\/div&gt;   &lt;\/div&gt; );  \/\/ \u0445\u0443\u043a function useWhyDidYouUpdate(name, props) {   \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 &quot;ref&quot; \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u043f\u0441\u043e\u0432   \/\/ \u0447\u0442\u043e\u0431\u044b \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u044c \u043f\u0440\u043e\u043f\u0441\u044b \u043f\u0440\u0438 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0435   const prevProps = useRef();    useEffect(() =&gt; {     if (prevProps.current) {       \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u043a\u043b\u044e\u0447\u0438 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0433\u043e \u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u0440\u043e\u043f\u0441\u043e\u0432       const allKeys = Object.keys({ ...prevProps.current, ...props });       \/\/ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u044d\u0442\u043e\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u043f\u0440\u043e\u043f\u0441\u043e\u0432       const changesObj = {};       \/\/ \u043f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0435\u043c \u043a\u043b\u044e\u0447\u0438       allKeys.forEach((key) =&gt; {         \/\/ \u0435\u0441\u043b\u0438 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e         if (prevProps.current[key] !== props[key]) {           \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043c \u0435\u0433\u043e \u0432 changesObj           changesObj[key] = {             from: prevProps.current[key],             to: props[key],           };         }       });        \/\/ \u0435\u0441\u043b\u0438 \u0432 changesObj \u0447\u0442\u043e-\u0442\u043e \u0435\u0441\u0442\u044c, \u0432\u044b\u0432\u043e\u0434\u0438\u043c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c       if (object.keys(changesObj).length) {         console.log(&quot;why-did-you-update&quot;, name, changesObj);       }     }      \/\/ \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c prevProps \u0442\u0435\u043a\u0443\u0449\u0438\u043c\u0438 \u043f\u0440\u043e\u043f\u0441\u0430\u043c\u0438 \u0434\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0432\u044b\u0437\u043e\u0432\u0430 \u0445\u0443\u043a\u0430     prevProps.current = props;   }); } <\/code><\/pre>\n<p>  <a name=\"useDarkMode\"><\/a><\/p>\n<h3>useDarkMode<\/h3>\n<p>  \u0414\u0430\u043d\u043d\u044b\u0439 \u0445\u0443\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043b\u043e\u0433\u0438\u043a\u0443 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0446\u0432\u0435\u0442\u043e\u0432\u043e\u0439 \u0441\u0445\u0435\u043c\u044b \u0441\u0430\u0439\u0442\u0430 (\u0441\u0432\u0435\u0442\u043b\u043e\u0439 \u0438 \u0442\u0435\u043c\u043d\u043e\u0439). \u0412 \u043d\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0445\u0435\u043c\u044b, \u0432\u044b\u0431\u0440\u0430\u043d\u043d\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c, \u0440\u0435\u0436\u0438\u043c\u0430 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e, \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0435\u0434\u0438\u0430-\u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u00abprefers-color-scheme\u00bb. \u0414\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0442\u0435\u043c\u043d\u043e\u0433\u043e \u0440\u0435\u0436\u0438\u043c\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u043b\u0430\u0441\u0441 \u00abdark-mode\u00bb \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u00abbody\u00bb. \u0425\u0443\u043a \u0442\u0430\u043a\u0436\u0435 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0441\u0438\u043b\u0443 \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u0438. \u0421\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0441 localStorage \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0445\u0443\u043a\u0430 \u00abuseLocalStorage\u00bb, \u0430 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u0441\u0445\u0435\u043c\u044b \u2014 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0445\u0443\u043a\u0430 \u00abuseMedia\u00bb, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0446\u0435\u043b\u0435\u0439. \u041e\u0434\u043d\u0430\u043a\u043e, \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u044f \u044d\u0442\u0438\u0445 \u0445\u0443\u043a\u043e\u0432 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0435\u0449\u0435 \u0431\u043e\u043b\u0435\u0435 \u043c\u043e\u0449\u043d\u043e\u043c\u0443 \u0445\u0443\u043a\u0443 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c \u0432\u0441\u0435\u0433\u043e \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430. \u042d\u0442\u043e \u043f\u043e\u0447\u0442\u0438 \u0442\u043e\u0436\u0435 \u0441\u0430\u043c\u043e\u0435, \u0447\u0442\u043e \u00ab\u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u043d\u0430\u044f\u00bb \u043c\u043e\u0449\u044c \u0445\u0443\u043a\u043e\u0432 \u043f\u043e \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044e \u043a \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432.<\/p>\n<pre><code class=\"javascript\">function App() {   const [darkMode, setDarkMode] = useDarkMode();    return (     &lt;div&gt;       &lt;div className=&quot;navbar&quot;&gt;         &lt;Toggle darkMode={darkMode} setDarkMode={setDarkMode} \/&gt;       &lt;\/div&gt;       &lt;Content \/&gt;     &lt;\/div&gt;   ); }  \/\/ \u0445\u0443\u043a function useDarkMode() {   \/\/ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0445\u0443\u043a &quot;useLocalStorage&quot; \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f   const [enabledState, setEnableState] = useLocalStorage(&quot;dark-mode-enabled&quot;);    \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0442\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0446\u0432\u0435\u0442\u043e\u0432\u043e\u0439 \u0441\u0445\u0435\u043c\u044b   \/\/ \u0432 \u0445\u0443\u043a\u0435 &quot;usePrefersDarkMode&quot; \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0445\u0443\u043a &quot;useMedia&quot;   const prefersDarkMode = usePrefersDarkMode();    \/\/ \u0435\u0441\u043b\u0438 enabledState \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0435\u0435, \u0438\u043d\u0430\u0447\u0435, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c prefersDarkMode   const enabled =     typeof enabledState !== &quot;undefined&quot; ? enabledState : prefersDarkMode;    \/\/ \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u044d\u0444\u0444\u0435\u043a\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f\/\u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u043a\u043b\u0430\u0441\u0441\u0430   useEffect(     () =&gt; {       const className = &quot;dark-mode&quot;;       const element = window.document.body;       if (enabled) {         element.classList.add(className);       } else {         element.classList.remove(className);       }     },     [enabled] \/\/ \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u044d\u0444\u0444\u0435\u043a\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 enabled   );    \/\/ \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c \u0438 \u0441\u0435\u0442\u0442\u0435\u0440   return [enabled, setEnableState]; }  \/\/ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u0445\u0443\u043a &quot;useMedia&quot; \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0439 \u0441\u0445\u0435\u043c\u044b \/\/ \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u044d\u0442\u043e\u0433\u043e \u0445\u0443\u043a\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0441\u0442\u0440\u0430\u043d\u043d\u043e, \u043d\u043e \u044d\u0442\u043e \u043e\u0431\u044a\u044f\u0441\u043d\u044f\u0435\u0442\u0441\u044f \u0442\u0435\u043c, \/\/ \u0447\u0442\u043e \u043e\u043d \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043c\u0435\u0434\u0438\u0430-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \/\/ \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043a\u0440\u044b\u0442\u044c \u0441\u043b\u043e\u0436\u043d\u044b\u0435 \u0434\u0435\u0442\u0430\u043b\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 function usePrefersDarkMode() {   return useMedia([&quot;(prefers-color-scheme: dark)&quot;], [true], false); } <\/code><\/pre>\n<p>  <a name=\"useMedia\"><\/a><\/p>\n<h3>useMedia<\/h3>\n<p>  \u0414\u0430\u043d\u043d\u044b\u0439 \u0445\u0443\u043a \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u0438\u0440\u0443\u0435\u0442 \u043b\u043e\u0433\u0438\u043a\u0443 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043c\u0435\u0434\u0438\u0430-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. \u0412 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u043c \u043d\u0438\u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043c\u044b \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043c \u0440\u0430\u0437\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u043b\u043e\u043d\u043e\u043a \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043c\u0435\u0434\u0438\u0430-\u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0439 \u0448\u0438\u0440\u0438\u043d\u0435 \u044d\u043a\u0440\u0430\u043d\u0430, \u0438 \u0437\u0430\u0442\u0435\u043c \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u043d\u0430\u0434 \u043a\u043e\u043b\u043e\u043d\u043a\u0430\u043c\u0438 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0442\u043e \u043e\u043d\u043e \u043d\u0438\u0432\u0435\u043b\u0438\u0440\u0443\u0435\u0442 \u0440\u0430\u0437\u043d\u0438\u0446\u0443 \u0432 \u0432\u044b\u0441\u043e\u0442\u0435 \u043a\u043e\u043b\u043e\u043d\u043e\u043a (\u043c\u044b \u043d\u0435 \u0445\u043e\u0442\u0438\u043c, \u0447\u0442\u043e\u0431\u044b \u043e\u0434\u043d\u0430 \u043a\u043e\u043b\u043e\u043d\u043a\u0430 \u0431\u044b\u043b\u0430 \u0432\u044b\u0448\u0435 \u0434\u0440\u0443\u0433\u043e\u0439). \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0445\u0443\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u0448\u0438\u0440\u0438\u043d\u0443 \u044d\u043a\u0440\u0430\u043d\u0430, \u043e\u0434\u043d\u0430\u043a\u043e \u043d\u0430\u0448 \u0445\u0443\u043a \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u043c\u0435\u0434\u0438\u0430-\u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u0435 \u0432 JS \u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 \u0441\u0442\u0438\u043b\u0435\u0439.<\/p>\n<pre><code class=\"javascript\">import { useState, useEffect } from &quot;react&quot;;  function App() {   const columnCount = useMedia(     \/\/ \u043c\u0435\u0434\u0438\u0430-\u0437\u0430\u043f\u0440\u043e\u0441\u044b     [&quot;(min-width: 1500px)&quot;, &quot;(min-width: 1000px)&quot;, &quot;(min-width: 600px)&quot;],     \/\/ \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u043b\u043e\u043d\u043e\u043a \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u0430     [5, 4, 3],     \/\/ \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043a\u043e\u043b\u043e\u043d\u043e\u043a \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e     2   );    \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u0432\u044b\u0441\u043e\u0442\u043e\u0439 \u043a\u043e\u043b\u043e\u043d\u043e\u043a (\u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 0)   let columnHeight = new Array(columnCount).fill(0);    \/\/ \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043c\u0430\u0441\u0441\u0438\u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u043e\u0432, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0445 \u043a\u0430\u0436\u0434\u0443\u044e \u043a\u043e\u043b\u043e\u043d\u043a\u0443   let columns = new Array(columnCount).fill().map(() =&gt; []);    data.forEach((item) =&gt; {     \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0438\u043d\u0434\u0435\u043a\u0441 \u0441\u0430\u043c\u043e\u0439 \u043a\u043e\u0440\u043e\u0442\u043a\u043e\u0439 \u043a\u043e\u043b\u043e\u043d\u043a\u0438     const shortColumntIndex = columnHeight.indexOf(Math.min(...columnHeight));     \/\/ \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442     columns[shortColumntIndex].push(item);     \/\/ \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0432\u044b\u0441\u043e\u0442\u0443     columnHeight[shortColumntIndex] += item.height;   });    \/\/ \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u043c \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u044b   return (     &lt;div className=&quot;App&quot;&gt;       &lt;div className=&quot;columns is-mobile&quot;&gt;         {columns.map((column) =&gt; (           &lt;div className=&quot;column&quot;&gt;             {column.map((item) =&gt; (               &lt;div                 className=&quot;image-container&quot;                 style={{                   \/\/ \u0440\u0430\u0437\u043c\u0435\u0440 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0435\u0433\u043e aspect ratio                   paddingTop: (item.height \/ item.width) * 100 + &quot;%&quot;,                 }}               &gt;                 &lt;img src={item.image} alt=&quot;&quot; \/&gt;               &lt;\/div&gt;             ))}           &lt;\/div&gt;         ))}       &lt;\/div&gt;     &lt;\/div&gt;   ); }  \/\/ \u0445\u0443\u043a function useMedia(queries, values, defaultValue) {   \/\/ \u043c\u0430\u0441\u0441\u0438\u0432 \u0441 \u043c\u0435\u0434\u0438\u0430-\u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438   const mediaQueryList = queries.map((q) =&gt; window.matchMedia(q));    \/\/ \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0430 \u043e\u0441\u043d\u043e\u0432\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430   const getValue = () =&gt; {     \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0438\u043d\u0434\u0435\u043a\u0441 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0441\u043e\u0432\u043f\u0430\u0432\u0448\u0435\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430     const index = mediaQueryList.findIndex((mql) =&gt; mql.matches);     \/\/ \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u043b\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e     return typeof values[index] !== &quot;undefined&quot;       ? values[index]       : defaultValue;   };    \/\/ \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u0441\u0435\u0442\u0442\u0435\u0440 \u0434\u043b\u044f \u0441\u043e\u0432\u043f\u0430\u0432\u0448\u0435\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f   const [value, setValue] = useState(getValue);    useEffect(     () =&gt; {       \/\/ \u043a\u043e\u043b\u0431\u044d\u043a \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0441\u043e\u0431\u044b\u0442\u0438\u0439       \/\/ \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435: \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044f getValue \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u043c\u0438 useEffect, \u043c\u044b \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u043c       \/\/ \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0442\u0435\u043a\u0443\u0449\u0438\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0445\u0443\u043a\u0430       \/\/ \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043a\u043e\u043b\u0431\u044d\u043a \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437 \u043f\u0440\u0438 \u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438       const handler = () =&gt; setValue(getValue);       \/\/ \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043c\u0435\u0434\u0438\u0430-\u0437\u0430\u043f\u0440\u043e\u0441\u0430       mediaQueryList.forEach((mql) =&gt; mql.addEventListener(handler));       \/\/ \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043d\u0430 \u0432\u044b\u0445\u043e\u0434\u0435       return () =&gt;         mediaQueryList.forEach((mql) =&gt; mql.removeEventListener(handler));     },     [] \/\/ \u043f\u0443\u0441\u0442\u043e\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0443\u0441\u043a \u044d\u0444\u0444\u0435\u043a\u0442\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438 \u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0438 \u0440\u0430\u0437\u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438   );    return value; } <\/code><\/pre>\n<p>  <a name=\"useLocalStorage\"><\/a><\/p>\n<h3>useLocalStorage<\/h3>\n<p>  \u0414\u0430\u043d\u043d\u044b\u0439 \u0445\u0443\u043a \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d \u0434\u043b\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0441 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435\u043c \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043c\u0435\u0436\u0434\u0443 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430\u043c\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u0445\u0443\u043a\u0430 \u043f\u043e\u0445\u043e\u0436\u0435 \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 useState, \u0437\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u043a\u043b\u044e\u0447 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f.<\/p>\n<pre><code class=\"javascript\">import { useState } from &quot;react&quot;;  \/\/ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 function App() {   \/\/ \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e useState, \u043d\u043e \u043f\u0435\u0440\u0432\u044b\u043c \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043b\u044e\u0447 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f, \u0445\u0440\u0430\u043d\u044f\u0449\u0435\u0433\u043e\u0441\u044f \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435   const [name, setName] = useLocalStorage(&quot;name&quot;, &quot;Igor&quot;);    return (     &lt;div&gt;       &lt;input         type=&quot;text&quot;         placeholder=&quot;Enter your name&quot;         value={name}         onChange={(e) =&gt; setName(e.target.value)}       \/&gt;     &lt;\/div&gt;   ); }  \/\/ \u0445\u0443\u043a function useLocalStorage(key, initialValue) {   \/\/ \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f   \/\/ \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 useState \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u043a\u0440\u0430\u0442\u043d\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f   const [storedValue, setStoredValue] = useState(() =&gt; {     try {       \/\/ \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u0437 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u043f\u043e \u043a\u043b\u044e\u0447\u0443       const item = window.localStorage.getItem(key);       \/\/ \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0438\u043b\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c initialValue       return item ? JSON.parse(item) : initialValue;     } catch (error) {       \/\/ \u0435\u0441\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430, \u0442\u0430\u043a\u0436\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435       console.error(error);       return initialValue;     }   });    \/\/ \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u0441\u0435\u0442\u0442\u0435\u0440\u0430 useState,   \/\/ \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u0442 \u043d\u043e\u0432\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435   const setValue = (value) =&gt; {     try {       \/\/ \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439       const valueToStore =         value instanceof Function ? value(storedValue) : value;       \/\/ \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435       setStoredValue(valueToStore);       \/\/ \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u0435\u0433\u043e \u0432 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435       window.localStorage.setItem(key, JSON.stringify(valueToStore));     } catch (error) {       \/\/ \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043e\u0448\u0438\u0431\u043e\u043a \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0432\u0438\u0434\u0430 \u043e\u0448\u0438\u0431\u043a\u0438       console.error(error);     }   };    return [storedValue, setValue]; } <\/code><\/pre>\n<p>  \u041d\u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u044d\u0442\u043e \u0432\u0441\u0435. \u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u0432\u044b \u043d\u0430\u0448\u043b\u0438 \u0434\u043b\u044f \u0441\u0435\u0431\u044f \u0447\u0442\u043e-\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0435. \u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435.<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/523034\/\"> https:\/\/habr.com\/ru\/post\/523034\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text-html post__text_v1\" id=\"post-content-body\" data-io-article-url=\"https:\/\/habr.com\/ru\/post\/523034\/\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/webt\/sj\/uf\/xu\/sjufxuqiadew2_zg3veuhlac7em.png\"><\/p>\n<p>  \u0414\u043e\u0431\u0440\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0443\u0442\u043e\u043a, \u0434\u0440\u0443\u0437\u044c\u044f!<\/p>\n<p>  \u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u044e \u043f\u0435\u0440\u0432\u0443\u044e \u0434\u0435\u0441\u044f\u0442\u043a\u0443 <a href=\"https:\/\/usehooks.com\/\" rel=\"nofollow\">\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0445\u0443\u043a\u043e\u0432<\/a>.<\/p>\n<p>  \u041e\u0433\u043b\u0430\u0432\u043b\u0435\u043d\u0438\u0435<\/p>\n<ul>\n<li><a href=\"#useMemoCompare\">useMemoCompare<\/a><\/li>\n<li><a href=\"#useAsync\">useAsync<\/a><\/li>\n<li><a href=\"#useRequireAuth\">useRequireAuth<\/a><\/li>\n<li><a href=\"#useRouter\">useRouter<\/a><\/li>\n<li><a href=\"#useAuth\">useAuth<\/a><\/li>\n<li><a href=\"#useEventListener\">useEventListener<\/a><\/li>\n<li><a href=\"#useWhyDidYouUpdate\">useWhyDidYouUpdate<\/a><\/li>\n<li><a href=\"#useDarkMode\">useDarkMode<\/a><\/li>\n<li><a href=\"#useMedia\">useMedia<\/a><\/li>\n<li><a href=\"#useLocalStorage\">useLocalStorage<\/a><\/li>\n<\/ul>\n<p>  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-311306","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/311306","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=311306"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/311306\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=311306"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=311306"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=311306"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}