{"id":412496,"date":"2024-06-29T22:34:37","date_gmt":"2024-06-29T22:34:37","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=412496"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=412496","title":{"rendered":"<span>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 mapbox-gl \u0432 React \u0438 Next.js<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0447\u0443 \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u043c\u043d\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u043d\u0438\u044f <code>mapbox-gl<\/code> \u0432 <code>React<\/code> \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0432\u0435\u0431 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0433\u043e \u043a\u0430\u0440\u0442\u0443 \u043d\u0430 <code>Next.js<\/code> \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <code>Typescript<\/code>, \u043a\u043e\u0434 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043a\u0430\u0440\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u043b\u044e\u0431\u043e\u043c \u043b\u044e\u0431\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043d\u0430 <code>React<\/code><\/p>\n<p>\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0432\u0445\u043e\u0434\u0438\u0442 \u0432 \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439<\/p>\n<div class=\"embed_link embed_layout-right\">\n<div class=\"embed__thumb\" style=\"background-image: url(&quot;https:\/\/habr.com\/share\/publication\/565216\/a299fc85e2e5805e0e5c65e16d01028b\/&quot;);\"><\/div>\n<div class=\"embed__caption\">\n<div class=\"embed__caption-title\"><span>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c mapbox-gl \u0432 React<\/span><\/div>\n<div class=\"embed__caption-description\">\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b\u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043c\u043e\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0432 geoalert.io \u044f \u043d\u0435 \u0440\u0430\u0437 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0441\u044f \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e&#8230;<\/div>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/565216\/\" target=\"_blank\" rel=\"noopener noreferrer nofollow\" class=\"embed__caption-link\">habr.com<\/a><\/div>\n<\/div>\n<p>\u042f \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u044e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043a\u0430\u0440\u0442\u044b:<\/p>\n<ul>\n<li>\n<p>\u0418\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0441 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u043c \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430 \u043a\u0430\u0440\u0442\u044b \u0432\u043d\u0443\u0442\u0440\u0438 <code>React<\/code> \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430<\/p>\n<\/li>\n<li>\n<p>\u0425\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430 \u043a\u0430\u0440\u0442\u044b \u0432\u043d\u0435 <code>React<\/code><\/p>\n<\/li>\n<\/ul>\n<h2>\u0421\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u0430\u043c \u0441 \u043a\u043e\u0434\u043e\u043c<\/h2>\n<blockquote>\n<p>\u200b\u200b \u0414\u043b\u044f \u043a\u043e\u043c\u0444\u043e\u0440\u0442\u043d\u043e\u0433\u043e \u0447\u0442\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0412\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u043c\u0435\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0437\u043d\u0430\u043d\u0438\u044f <code>React<\/code>, <code>Typescript<\/code> \u0438 <code>CSS<\/code><\/p>\n<\/blockquote>\n<blockquote>\n<p>\u200b\u200b \u0412\u0441\u0435 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u044b \u0441 \u043a\u043e\u0434\u043e\u043c \u0431\u0443\u0434\u0443\u0442 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <code>Typescript<\/code>, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 javascript \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0443\u0447\u0448\u0435\u0439 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u043e\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0438\u0430\u043b\u044c\u043d\u043e \u0435\u0435 \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0441\u044c \u0442\u0430\u043c \u0433\u0434\u0435 \u044d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043f\u0440\u043e\u0448\u0443 \u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0435\u0441\u043b\u0438 \u0432\u044b \u0435\u0435 \u043d\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u044b \u0441 \u043d\u0438\u043c, <a href=\"https:\/\/egghead.io\/courses\/up-and-running-with-typescript\" rel=\"noopener noreferrer nofollow\">\u0432\u043e\u0442 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u0443\u0440\u0441 \u043e\u0442 egghead.io \u0433\u0434\u0435 \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0441 \u043d\u0438\u043c \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f<\/a> <\/p>\n<\/blockquote>\n<blockquote>\n<p>\u200b\u200b \u042f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u044e \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c <code>React<\/code> \u043a\u0430\u043a <code>import * as React from \"react\"<\/code> \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 <a href=\"https:\/\/epicreact.dev\/importing-react-through-the-ages\/\" rel=\"noopener noreferrer nofollow\">\u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0430\u0440\u0442\u0438\u043a\u043b\u0435 \u043e\u0442  Kent C. Dodds<\/a><\/p>\n<\/blockquote>\n<blockquote>\n<p>\u200b\u200b \u0415\u0441\u043b\u0438 \u0432 \u043a\u043e\u0434\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f <code>\/\/ ...<\/code> \u044d\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0447\u0438\u0442\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u0435\u0441\u0442\u0430 \u0441 \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u043c \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u043c\u0441\u044f \u043a\u043e\u0434\u043e\u043c<\/p>\n<\/blockquote>\n<h2>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/h2>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 <code>Next.js<\/code> \u043f\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0443 <code>Typescript<\/code><\/p>\n<pre><code class=\"bash\">npx create-next-app --typescript my-awesome-app<\/code><\/pre>\n<p>\u041e\u0442\u043a\u0440\u043e\u0435\u043c \u043f\u0430\u043f\u043a\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0442\u0430\u043a \u0436\u0435 <code>mapbox-gl<\/code> \u0441 \u0442\u0438\u043f\u0430\u043c\u0438 \u0434\u043b\u044f <code>Typescript<\/code><\/p>\n<pre><code class=\"bash\">cd my-awesome-app  npm install --save mapbox-gl &amp;&amp; npm install -D @types\/mapbox-gl<\/code><\/pre>\n<p>\u0422\u0430\u043a \u0436\u0435 \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/docs.mapbox.com\/help\/getting-started\/access-tokens\/\" rel=\"noopener noreferrer nofollow\">accessToken<\/a> \u0434\u043b\u044f <code>mapbox-gl<\/code> \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u0435\u0433\u043e \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u043a\u043e\u0434\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/p>\n<pre><code class=\"bash\">touch .env.local  echo NEXT_PUBLIC_MAPBOX_TOKEN=&lt;\u0432\u0430\u0448_\u0442\u043e\u043a\u0435\u043d> >> .env.local<\/code><\/pre>\n<p>\u0422\u0430\u043a \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0432\u0430\u0448 \u0444\u0430\u0439\u043b \u0441 <a href=\"https:\/\/nextjs.org\/docs\/basic-features\/environment-variables\" rel=\"noopener noreferrer nofollow\">\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f <\/a><code>Next.js<\/code><\/p>\n<p><strong>.env.local<\/strong><\/p>\n<pre><code class=\"bash\">NEXT_PUBLIC_MAPBOX_TOKEN=&lt;\u0432\u0430\u0448_\u0442\u043e\u043a\u0435\u043d><\/code><\/pre>\n<h2>\u0418\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0432 \u0432\u0438\u0434\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 React<\/h2>\n<h3>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0441\u0442\u0438\u043b\u0435\u0439<\/h3>\n<p>\u0423\u0434\u0430\u043b\u0438\u043c \u043b\u0438\u0448\u043d\u0438\u0435 \u0441\u0442\u0438\u043b\u0438 \u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u043c \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0441\u0442\u0438\u043b\u0435\u0439<\/p>\n<pre><code class=\"bash\">rm styles\/Home.module.css<\/code><\/pre>\n<p><strong>styles\/global.css<\/strong><\/p>\n<pre><code class=\"css\">html, body, #__next {   padding: 0;   margin: 0;   width: 100%;   height: 100%; }  * {   box-sizing: border-box; } <\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432\u044b\u0441\u043e\u0442\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0440\u0430\u0432\u043d\u044f\u043b\u0430\u0441\u044c <code>100%<\/code> \u0432\u044b\u0441\u043e\u0442\u044b \u043e\u043a\u043d\u0430, \u0437\u0430\u0434\u0430\u0434\u0438\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 <code>width<\/code> \u0438 <code>height<\/code> \u0440\u0430\u0432\u043d\u044b\u0435 <code>100%<\/code> \u0434\u043b\u044f <code>html<\/code> \u0438 <code>body<\/code> <\/p>\n<p>\u0412\u044b\u0441\u043e\u0442\u0443 \u0442\u0430\u043a \u0436\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u043b\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0441 <code>css<\/code> \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u043e\u043c <code>#__next<\/code> \u0442\u0430\u043a \u043a\u0430\u043a \u0432 <code>Next.js<\/code> \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043a\u043e\u0440\u043d\u0435\u0432\u044b\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <code>&lt;div id=\"__next\">...&lt;\/div><\/code><\/p>\n<h3>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043a\u0430\u0440\u0442\u044b<\/h3>\n<p><strong>components\/mapbox-map.tsx<\/strong><\/p>\n<pre><code class=\"java\">import * as React from \"react\"; import mapboxgl from \"mapbox-gl\"; import \"mapbox-gl\/dist\/mapbox-gl.css\";  \/\/ \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0441\u0442\u0438\u043b\u0438 mapbox-gl \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0440\u0442\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u043b\u0430\u0441\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u043d\u043e  function MapboxMap() {     \/\/ \u0437\u0434\u0435\u0441\u044c \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043a\u0430\u0440\u0442\u044b \u043f\u043e\u0441\u043b\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438   const [map, setMap] = React.useState&lt;mapboxgl.Map>();    \/\/ React ref \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 DOM \u043d\u043e\u0434\u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442    \/\/ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 `container`    \/\/ \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u0430\u0440\u0442\u044b `mapbox-gl`   \/\/ \u043f\u043e-\u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c `null`     const mapNode = React.useRef(null);    React.useEffect(() => {     const node = mapNode.current;         \/\/ \u0435\u0441\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442 window \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d,         \/\/ \u0442\u043e \u0435\u0441\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435         \/\/ \u0438\u043b\u0438 dom node \u043d\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0430, \u0442\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c     if (typeof window === \"undefined\" || node === null) return;      \/\/ \u0438\u043d\u0430\u0447\u0435 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043a\u0430\u0440\u0442\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0435\u043c\u0443 \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 DOM \u043d\u043e\u0434\u0443     \/\/ \u0430 \u0442\u0430\u043a\u0436\u0435 accessToken \u0434\u043b\u044f mapbox     const mapboxMap = new mapboxgl.Map({       container: node,             accessToken: process.env.NEXT_PUBLIC_MAPBOX_TOKEN,             style: \"mapbox:\/\/styles\/mapbox\/streets-v11\",       center: [-74.5, 40],       zoom: 9,     });      \/\/ \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u0430\u0440\u0442\u044b \u0432 React.useState     setMap(mapboxMap);          \/\/ \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0443\u0442\u0435\u0447\u043a\u0438 \u043f\u0430\u043c\u044f\u0442\u0438 \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043a\u0430\u0440\u0442\u044b \/\/ \u043a\u043e\u0433\u0434\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d     return () => {       mapboxMap.remove();     };   }, []);      return &lt;div ref={mapNode} style={{ width: \"100%\", height: \"100%\" }} \/>; }  export default MapboxMap <\/code><\/pre>\n<p>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <code>mapbox-gl<\/code> \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 <\/p>\n<div class=\"embed_link\">\n<div class=\"embed__thumb\" style=\"background-image: url(&quot;https:\/\/static-assets.mapbox.com\/branding\/social\/social-1200x630.v2.jpg&quot;);\"><\/div>\n<div class=\"embed__caption\">\n<div class=\"embed__caption-title\"><span>Map | Mapbox GL JS<\/span><\/div>\n<p><a href=\"https:\/\/docs.mapbox.com\/mapbox-gl-js\/api\/map\/\" target=\"_blank\" rel=\"noopener noreferrer nofollow\" class=\"embed__caption-link\">docs.mapbox.com<\/a><\/div>\n<\/div>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \u0432 \u0433\u043b\u0430\u0432\u043d\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442<\/p>\n<p><strong>pages\/index.tsx<\/strong><\/p>\n<pre><code class=\"java\">import MapboxMap from \"..\/components\/mapbox-map\";  function App() {   return &lt;MapboxMap \/>; }  export default App; <\/code><\/pre>\n<pre><code class=\"bash\">npm run dev<\/code><\/pre>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432 <a href=\"http:\/\/localhost:3000\" rel=\"noopener noreferrer nofollow\">http:\/\/localhost:3000<\/a> \u0432\u0438\u0434\u0438\u043c \u043f\u043e\u043b\u043d\u043e\u044d\u043a\u0440\u0430\u043d\u043d\u0443\u044e \u0432\u0435\u0431-\u043a\u0430\u0440\u0442\u0443<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/ed2\/4a9\/731\/ed24a973103d68468b5c526439b729f0.png\" width=\"3360\" height=\"2026\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ed2\/4a9\/731\/ed24a973103d68468b5c526439b729f0.png\"\/><\/figure>\n<h3>\u0427\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043b\u0443\u0447\u0448\u0435<\/h3>\n<p>\u0412 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0444\u0438\u0447\u0435\u0439<\/p>\n<ul>\n<li>\n<p><strong>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u0430\u0440\u0442\u044b<\/strong> &#8212; \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043a\u0430\u0440\u0442\u044b \u043b\u043e\u0433\u0438\u0447\u043d\u044b\u043c \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0435\u043c\u0443 \u0447\u0435\u0440\u0435\u0437 <code>props<\/code> \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043a\u0430\u0440\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u0414<strong>\u043e\u0441\u0442\u0443\u043f \u043a \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0443 \u043a\u0430\u0440\u0442\u044b \u0438\u0437 \u0434\u0440\u0443\u0433\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 &#8212; \u043f<\/strong>\u043e\u043c\u0438\u043c\u043e \u0441\u0430\u043c\u043e\u0439 \u0432\u0435\u0431-\u043a\u0430\u0440\u0442\u044b \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0434\u0440\u0443\u0433\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u043c\u0435\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043a \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0443 \u043a\u0430\u0440\u0442\u044b<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u043e\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043e \u0433\u043e\u0442\u043e\u0432\u043d\u043e\u0441\u0442\u0438 \u043a\u0430\u0440\u0442\u044b<\/strong> &#8212; \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043a\u0430\u0440\u0442\u044b \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f, \u043f\u043e\u043a\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u043a\u0430\u0440\u0442\u044b,  \u0434\u043b\u044f \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043e\u043f\u044b\u0442\u0430, \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u043a\u0435\u043b\u0435\u0442\u043e\u043d \u0438\u043b\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d \u0441\u043e \u0441\u043f\u0438\u043d\u043d\u0435\u0440\u043e\u043c. \u0414\u043b\u044f \u044d\u0442\u0438\u0445 \u0446\u0435\u043b\u0435\u0439 \u0431\u044b\u043b\u043e \u0431\u044b \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u043c\u0435\u0442\u044c \u043a\u043e\u043b\u043b\u0431\u0435\u043a \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u043a\u0430\u0440\u0442\u0430 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0441 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 \u043a\u0430\u0440\u0442\u044b \u0432 \u043c\u043e\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 <a href=\"https:\/\/app.mapflow.ai\" rel=\"noopener noreferrer nofollow\">https:\/\/app.mapflow.ai<\/a><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/34f\/720\/c1c\/34f720c1ceae2e449c0c9d42f5127ac8.gif\" width=\"768\" height=\"443\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/34f\/720\/c1c\/34f720c1ceae2e449c0c9d42f5127ac8.gif\"\/><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d79\/f27\/3e9\/d79f273e90b06b3a9b47199337d06cd4.png\" width=\"1008\" height=\"658\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d79\/f27\/3e9\/d79f273e90b06b3a9b47199337d06cd4.png\"\/><\/figure>\n<h2>\u0423\u043b\u0443\u0447\u0448\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043a\u0430\u0440\u0442\u044b<\/h2>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u044d\u0442\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c <code>props<\/code> \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0432\u0435\u0431-\u043a\u0430\u0440\u0442\u044b<\/p>\n<pre><code class=\"java\">interface MapboxMapProps {   initialOptions?: Omit&lt;mapboxgl.MapboxOptions, \"container\">;   onCreated?(map: mapboxgl.Map): void;   onLoaded?(map: mapboxgl.Map): void;   onRemoved?(): void; }  function MapboxMap({   initialOptions = {},   onCreated,   onLoaded,   onRemoved, }: MapboxMapProps) {     \/\/ ... <\/code><\/pre>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 <code>props<\/code><\/p>\n<ul>\n<li>\n<p><strong>initialOptions<\/strong> &#8212; <a href=\"https:\/\/www.notion.so\/mapbox-gl-React-Next-js-fac7c457b2da4d0aa8a0a2579e7e10c8\" rel=\"noopener noreferrer nofollow\">\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u0430\u0440\u0442\u044b<\/a>, \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>container<\/code> \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <code>MapboxOptions<\/code> \u0432 \u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/utility-types.html\" rel=\"noopener noreferrer nofollow\">\u0443\u0442\u0438\u043b\u0438\u0442\u0430\u0440\u043d\u044b\u0439 \u0442\u0438\u043f <\/a><code>Omit<\/code><\/p>\n<\/li>\n<li>\n<p><strong>onCreated<\/strong> &#8212; \u043a\u043e\u043b\u043b\u0431\u0435\u043a \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u043f\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430 \u043a\u0430\u0440\u0442\u044b<\/p>\n<\/li>\n<li>\n<p><strong>onLoaded<\/strong> &#8212; \u043a\u043e\u043b\u043b\u0431\u0435\u043a \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u043f\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044e \u043f\u043e\u043b\u043d\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043a\u0430\u0440\u0442\u044b<\/p>\n<\/li>\n<li>\n<p><strong>onRemoved<\/strong> &#8212; \u043a\u043e\u043b\u043b\u0431\u0435\u043a \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430 \u043a\u0430\u0440\u0442\u044b<\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>container<\/code> \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <code>MapboxOptions<\/code> \u0432 \u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/utility-types.html\" rel=\"noopener noreferrer nofollow\">\u0443\u0442\u0438\u043b\u0438\u0442\u0430\u0440\u043d\u044b\u0439 \u0442\u0438\u043f <\/a><code>Omit<\/code><\/p>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c <code>initialOptions<\/code> \u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0435\u0431-\u043a\u0430\u0440\u0442\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <a href=\"https:\/\/developer.mozilla.org\/ru\/docs\/Web\/JavaScript\/Reference\/Operators\/Spread_syntax#spread_%D0%B2_%D0%BB%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D0%BB%D0%B0%D1%85_%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%B0\" rel=\"noopener noreferrer nofollow\">spread syntax<\/a>, \u0442\u0430\u043a \u0436\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043a\u0430\u0440\u0442\u044b, \u0435\u0441\u043b\u0438 \u043a\u043e\u043b\u043b\u0431\u0435\u043a <code>onMapLoaded<\/code>, \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0441\u043b\u0438 \u043e\u043d \u0431\u044b\u043b \u043f\u0435\u0440\u0435\u0434\u0430\u043d \u0432 <code>props<\/code> \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0434\u043b\u044f <code>onMapRemoved<\/code><\/p>\n<pre><code class=\"java\">\/\/ ...     const mapboxMap = new mapboxgl.Map({       container: node,       accessToken: process.env.NEXT_PUBLIC_MAPBOX_TOKEN,       style: \"mapbox:\/\/styles\/mapbox\/streets-v11\",       center: [-74.5, 40],       zoom: 9,       ...initialOptions,     });      setMap(mapboxMap);     if (onCreated) onCreated(mapboxMap)  \/\/ \u0435\u0441\u043b\u0438 onLoaded \u0443\u043a\u0430\u0437\u0430\u043d, \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u0432\u0430\u043d \u0435\u0434\u0438\u043d\u043e\u0436\u0434\u044b     \/\/ \u043f\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043a\u0430\u0440\u0442\u044b if (onLoaded) mapboxMap.once(\"load\", () => onLoaded(mapboxMap));  return () => {       mapboxMap.remove();       setMap(undefined);       if (onRemoved) onRemoved();     };      \/\/ eslint-disable-next-line react-hooks\/exhaustive-deps   }, []);  \/\/ ...<\/code><\/pre>\n<p>\u0422\u0443\u0442 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u0434\u043b\u044f \u043b\u0438\u043d\u0442\u0435\u0440\u0430 <\/p>\n<pre><code class=\"javascript\">\/\/ eslint-disable-next-line react-hooks\/exhaustive-deps<\/code><\/pre>\n<p>\u0421\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u043e\u0431\u0449\u0435\u043f\u0440\u0438\u043d\u044f\u0442\u043e\u043c\u0443 \u043f\u0440\u0430\u0432\u0438\u043b\u0443 <code>react-hooks\/exhaustive-deps<\/code> \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u043b\u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0434\u043b\u044f <code>React.useEffect<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0432 \u0445\u0443\u043a \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 <code>[initialOptions, onMapLoaded, onMapRemoved]<\/code><\/p>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u0430\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u043f\u0443\u0441\u0442\u044b\u043c, \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0435 \u043f\u0435\u0440\u0435\u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043a\u0430\u0440\u0442\u044b \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0435\u0441\u043b\u0438 <code>initialOptions<\/code> \u0438\u043b\u0438 <code>onMapLoaded<\/code> \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u0441\u044f, \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 <code>React.useEffect<\/code> \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 \u043d\u0438\u0436\u0435<\/p>\n<div class=\"embed_link\">\n<div class=\"embed__thumb\" style=\"background-image: url(&quot;undefined&quot;);\"><\/div>\n<div class=\"embed__caption\">\n<div class=\"embed__caption-title\"><span>A Complete Guide to useEffect<\/span><\/div>\n<p><a href=\"https:\/\/overreacted.io\/a-complete-guide-to-useeffect\/\" target=\"_blank\" rel=\"noopener noreferrer nofollow\" class=\"embed__caption-link\">overreacted.io<\/a><\/div>\n<\/div>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a<\/p>\n<p><strong>components\/mapbox-map.tsx<\/strong><\/p>\n<pre><code class=\"java\">import * as React from \"react\"; import mapboxgl from \"mapbox-gl\"; import \"mapbox-gl\/dist\/mapbox-gl.css\";  interface MapboxMapProps {   initialOptions?: Omit&lt;mapboxgl.MapboxOptions, \"container\">;   onCreated?(map: mapboxgl.Map): void;   onLoaded?(map: mapboxgl.Map): void;   onRemoved?(): void; }  function MapboxMap({   initialOptions = {},   onCreated,   onLoaded,   onRemoved, }: MapboxMapProps) {   const [map, setMap] = React.useState&lt;mapboxgl.Map>();    const mapNode = React.useRef(null);    React.useEffect(() => {     const node = mapNode.current;      if (typeof window === \"undefined\" || node === null) return;      const mapboxMap = new mapboxgl.Map({       container: node,       accessToken: process.env.NEXT_PUBLIC_MAPBOX_TOKEN,       style: \"mapbox:\/\/styles\/mapbox\/streets-v11\",       center: [-74.5, 40],       zoom: 9,       ...initialOptions,     });      setMap(mapboxMap);     if (onCreated) onCreated(mapboxMap);      if (onLoaded) mapboxMap.once(\"load\", () => onLoaded(mapboxMap));      return () => {       mapboxMap.remove();       setMap(undefined);       if (onRemoved) onRemoved();     };      \/\/ eslint-disable-next-line react-hooks\/exhaustive-deps   }, []);    return &lt;div ref={mapNode} style={{ width: \"100%\", height: \"100%\" }} \/>; }  export default MapboxMap;<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043a\u0430\u0440\u0442\u044b \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043b\u043b\u0431\u0435\u043a <code>onMapLoaded<\/code> \u043f\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044e \u0435\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u0422\u0430\u043a \u0436\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>onMapLoaded<\/code> \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043a\u0430\u0440\u0442\u044b \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435. \u0422\u0430\u043a \u0436\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>onMapRemoved<\/code> \u0435\u0441\u043b\u0438 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0437\u043d\u0430\u0442\u044c \u0447\u0442\u043e \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043a\u0430\u0440\u0442\u044b \u0431\u044b\u043b \u0443\u0434\u0430\u043b\u0435\u043d.<\/p>\n<p>\u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u044d\u0442\u0438\u043c, \u0443\u043a\u0430\u0436\u0435\u043c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0446\u0435\u043d\u0442\u0440\u0430 \u043a\u0430\u0440\u0442\u044b, \u0430 \u0442\u0430\u043a \u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043a\u0430\u0440\u0442\u044b.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 <code>MapLoadingHolder<\/code> \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0432\u0435\u0440\u0445 \u043a\u0430\u0440\u0442\u044b \u043f\u043e\u043a\u0430 \u043e\u043d\u0430 \u043d\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430.<\/p>\n<p>\u0414\u043b\u044f \u044d\u043a\u0440\u0430\u043d\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u0430\u043c \u0442\u0430\u043a \u0436\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 <code>svg<\/code> \u0438\u043a\u043e\u043d\u043a\u0430, \u044f \u0435\u0435 \u0441 <a href=\"https:\/\/www.freepik.com\" rel=\"noopener noreferrer nofollow\">Freepic<\/a>, \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0432 \u0435\u0435 \u0432 jsx \u0444\u043e\u0440\u043c\u0430\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/svg2jsx.com\/\" rel=\"noopener noreferrer nofollow\">https:\/\/svg2jsx.com\/<\/a><\/p>\n<p><strong>components\/world-icon.tsx<\/strong><\/p>\n<pre><code class=\"java\">function WorldIcon({ className = \"\" }: { className?: string }) {   return (     &lt;svg       className={className}       xmlns=\"http:\/\/www.w3.org\/2000\/svg\"       width=\"48.625\"       height=\"48.625\"       x=\"0\"       y=\"0\"       enableBackground=\"new 0 0 48.625 48.625\"       version=\"1.1\"       viewBox=\"0 0 48.625 48.625\"       xmlSpace=\"preserve\"     >       &lt;path d=\"M35.432 10.815L35.479 11.176 34.938 11.288 34.866 12.057 35.514 12.057 36.376 11.974 36.821 11.445 36.348 11.261 36.089 10.963 35.7 10.333 35.514 9.442 34.783 9.591 34.578 9.905 34.578 10.259 34.93 10.5z\">&lt;\/path>       &lt;path d=\"M34.809 11.111L34.848 10.629 34.419 10.444 33.819 10.583 33.374 11.297 33.374 11.76 33.893 11.76z\">&lt;\/path>       &lt;path d=\"M22.459 13.158l-.132.34h-.639v.33h.152l.022.162.392-.033.245-.152.064-.307.317-.027.125-.258-.291-.06-.255.005z\">&lt;\/path>       &lt;path d=\"M20.812 13.757L20.787 14.08 21.25 14.041 21.298 13.717 21.02 13.498z\">&lt;\/path>       &lt;path d=\"M48.619 24.061a24.552 24.552 0 00-.11-2.112 24.165 24.165 0 00-1.609-6.62c-.062-.155-.119-.312-.185-.465a24.341 24.341 0 00-4.939-7.441 24.19 24.19 0 00-1.11-1.086A24.22 24.22 0 0024.312 0c-6.345 0-12.126 2.445-16.46 6.44a24.6 24.6 0 00-2.78 3.035A24.18 24.18 0 000 24.312c0 13.407 10.907 24.313 24.313 24.313 9.43 0 17.617-5.4 21.647-13.268a24.081 24.081 0 002.285-6.795c.245-1.381.379-2.801.379-4.25.001-.084-.004-.167-.005-.251zm-4.576-9.717l.141-.158c.185.359.358.724.523 1.094l-.23-.009-.434.06v-.987zm-3.513-4.242l.004-1.086c.382.405.75.822 1.102 1.254l-.438.652-1.531-.014-.096-.319.959-.487zM11.202 7.403v-.041h.487l.042-.167h.797v.348l-.229.306h-1.098l.001-.446zm.778 1.085s.487-.083.529-.083 0 .486 0 .486l-1.098.069-.209-.25.778-.222zm33.612 9.651h-1.779l-1.084-.807-1.141.111v.696h-.361l-.39-.278-1.976-.501v-1.28l-2.504.195-.776.417h-.994l-.487-.049-1.207.67v1.261l-2.467 1.78.205.76h.5l-.131.724-.352.129-.019 1.892 2.132 2.428h.928l.056-.148h1.668l.481-.445h.946l.519.52 1.41.146-.187 1.875 1.565 2.763-.824 1.575.056.742.649.647v1.784l.852 1.146v1.482h.736c-4.096 5.029-10.33 8.25-17.305 8.25C12.009 46.625 2 36.615 2 24.312c0-3.097.636-6.049 1.781-8.732v-.696l.798-.969c.277-.523.574-1.033.891-1.53l.036.405-.926 1.125a22.14 22.14 0 00-.798 1.665v1.27l.927.446v1.765l.889 1.517.723.111.093-.52-.853-1.316-.167-1.279h.5l.211 1.316 1.233 1.799-.318.581.784 1.199 1.947.482v-.315l.779.111-.074.556.612.112.945.258 1.335 1.521 1.705.129.167 1.391-1.167.816-.055 1.242-.167.76 1.688 2.113.129.724s.612.166.687.166c.074 0 1.372.983 1.372.983v3.819l.463.13-.315 1.762.779 1.039-.144 1.746 1.029 1.809 1.321 1.154 1.328.024.13-.427-.976-.822.056-.408.175-.5.037-.51-.66-.02-.333-.418.548-.527.074-.398-.612-.175.036-.37.872-.132 1.326-.637.445-.816 1.391-1.78-.316-1.392.427-.741 1.279.039.861-.682.278-2.686.955-1.213.167-.779-.871-.279-.575-.943-1.965-.02-1.558-.594-.074-1.111-.52-.909-1.409-.021-.814-1.278-.723-.353-.037.39-1.316.078-.482-.671-1.373-.279-1.131 1.307-1.78-.302-.129-2.006-1.299-.222.521-.984-.149-.565-1.707 1.141-1.074-.131-.383-.839.234-.865.592-1.091 1.363-.69 2.632-.001-.007.803.946.44-.075-1.372.682-.686 1.376-.904.094-.636 1.372-1.428 1.459-.808-.129-.106.988-.93.362.096.166.208.375-.416.092-.041-.411-.058-.417-.139v-.4l.221-.181h.487l.223.098.193.39.236-.036v-.034l.068.023.684-.105.097-.334.39.098v.362l-.362.249h.001l.053.397 1.239.382.003.015.285-.024.019-.537-.982-.447-.056-.258.815-.278.036-.78-.852-.519-.056-1.315-1.168.574h-.426l.112-1.001-1.59-.375-.658.497v1.516l-1.183.375-.474.988-.514.083v-1.264l-1.112-.154-.556-.362-.224-.819 1.989-1.164.973-.296.098.654.542-.028.042-.329.567-.081.01-.115-.244-.101-.056-.348.697-.059.421-.438.023-.032.005.002.128-.132 1.465-.185.648.55-1.699.905 2.162.51.28-.723h.945l.334-.63-.668-.167v-.797l-2.095-.928-1.446.167-.816.427.056 1.038-.853-.13-.131-.574.817-.742-1.483-.074-.426.129-.185.5.556.094-.111.556-.945.056-.148.37-1.371.038s-.038-.778-.093-.778l1.075-.019.817-.798-.446-.223-.593.576-.984-.056-.593-.816h-1.261l-1.316.983h1.206l.11.353-.313.291 1.335.037.204.482-1.503-.056-.073-.371-.945-.204-.501-.278-1.125.009A22.188 22.188 0 0124.312 2c5.642 0 10.797 2.109 14.73 5.574l-.265.474-1.029.403-.434.471.1.549.531.074.32.8.916-.369.151 1.07h-.276l-.752-.111-.834.14-.807 1.14-1.154.181-.167.988.487.115-.141.635-1.146-.23-1.051.23-.223.585.182 1.228.617.289 1.035-.006.699-.063.213-.556 1.092-1.419.719.147.708-.64.132.5 1.742 1.175-.213.286-.785-.042.302.428.483.106.566-.236-.012-.682.251-.126-.202-.214-1.162-.648-.306-.861h.966l.309.306.832.717.035.867.862.918.321-1.258.597-.326.112 1.029.583.64 1.163-.02c.225.579.427 1.168.604 1.769l-.121.112zm-32.331-7.093l.584-.278.528.126-.182.709-.57.181-.36-.738zm3.099 1.669v.459h-1.334l-.5-.139.125-.32.641-.265h.876v.265h.192zm.614.64v.445l-.334.215-.416.077v-.737h.75zm-.376-.181v-.529l.459.418-.459.111zm.209 1.07v.433l-.319.32h-.709l.111-.486.335-.029.069-.167.513-.071zm-1.766-.889h.737l-.945 1.321-.39-.209.084-.556.514-.556zm3.018.737v.432h-.709l-.194-.28v-.402h.056l.847.25zm-.655-.594l.202-.212.341.212-.273.225-.27-.225zm28.55 5.767l.07-.082c.029.126.06.252.088.38l-.158-.298z\">&lt;\/path>       &lt;path d=\"M3.782 14.884v.696c.243-.568.511-1.122.798-1.665l-.798.969z\">&lt;\/path>     &lt;\/svg>   ); }  export default WorldIcon; <\/code><\/pre>\n<p><strong>components\/map-loading-holder.tsx<\/strong><\/p>\n<pre><code class=\"java\">import WorldIcon from \"..\/components\/world-icon\";  function MapLoadingHolder() {   return (     &lt;div className=\"loading-holder\">       &lt;WorldIcon className=\"icon\" \/>       &lt;h1>Initializing the map&lt;\/h1>       &lt;div className=\"icon-attribute\">         Icons made by{\" \"}         &lt;a href=\"https:\/\/www.freepik.com\" title=\"Freepik\">           Freepik         &lt;\/a>{\" \"}         from{\" \"}         &lt;a href=\"https:\/\/www.flaticon.com\/\" title=\"Flaticon\">           www.flaticon.com         &lt;\/a>       &lt;\/div>     &lt;\/div>   ); }  export default MapLoadingHolder; <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0431\u0435\u0440\u0435\u043c \u0432\u0441\u0435 \u0432\u043c\u0435\u0441\u0442\u0435, \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 <code>.app-container<\/code>, \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0443\u0434\u0443\u0442 \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u043a\u0430\u0440\u0442\u044b \u043f\u043e\u043c\u0435\u0449\u0435\u043d\u043d\u044b\u0439 \u0432 <code>map-wrapper<\/code> \u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 <code>MapLoadingHolder<\/code><\/p>\n<p>\u0414\u043e\u0431\u0430\u0432\u0438\u043c \u0442\u0430\u043a \u0436\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 <code>&lt;Head>...&lt;\/Head><\/code> \u0432 \u043d\u0435\u043c \u043c\u043e\u0436\u043d\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u043c\u0435\u0442\u0430-\u0442\u0435\u0433\u0438 \u0438 <code>title<\/code> \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u0430<\/p>\n<p><strong>pages\/index.tsx<\/strong><\/p>\n<pre><code class=\"java\">import * as React from \"react\"; import Head from \"next\/head\"; import MapboxMap from \"..\/components\/mapbox-map\"; import MapLoadingHolder from \"..\/components\/map-loading-holder\";  function App() {   const [loading, setLoading] = React.useState(true);   const handleMapLoading = () => setLoading(false);    return (     &lt;>       &lt;Head>         &lt;title>Using mapbox-gl with React and Next.js&lt;\/title>       &lt;\/Head>       &lt;div className=\"app-container\">         &lt;div className=\"map-wrapper\">           &lt;MapboxMap             initialOptions={{ center: [38.0983, 55.7038] }}             onMapLoaded={handleMapLoading}           \/>         &lt;\/div>         {loading &amp;&amp; &lt;MapLoadingHolder className=\"loading-holder\" \/>}       &lt;\/div>     &lt;\/>   ); }  export default App; <\/code><\/pre>\n<p>\u0412\u043d\u0435\u0441\u0435\u043c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u0443\u044e\u0449\u0438\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0441\u0442\u0438\u043b\u0438, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439 \u0444\u043e\u043d \u0434\u043b\u044f <code>.loading-holder<\/code>, \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0437\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u043f\u043e \u0446\u0435\u043d\u0442\u0440\u0443, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u0443\u043b\u044c\u0441\u0438\u0440\u0443\u044e\u0449\u0443\u044e \u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0438\u043a\u043e\u043d\u043a\u0438, \u0442\u0430\u043a \u043a\u0430\u043a \u0444\u043e\u043d \u043f\u043e\u043b\u0443\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u044b\u0439, \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u0446\u0432\u0435\u0442\u043d\u0443\u044e \u0442\u0435\u043d\u044c <code>text-shadow: 0px 0px 10px rgba(152, 207, 195, 0.7);<\/code> \u043a \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0443 <code>&lt;h1>Initializing the map&lt;\/h1><\/code>, \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 \u043c\u043e\u0435\u043c \u043f\u043e\u0441\u0442\u0435 \u043f\u0440\u043e \u0442\u0435\u043a\u0441\u0442 \u043d\u0430 \u0446\u0432\u0435\u0442\u043d\u043e\u043c \u0444\u043e\u043d\u0435<\/p>\n<div class=\"embed_link\">\n<div class=\"embed__thumb\" style=\"background-image: url(&quot;https:\/\/s.gravatar.com\/avatar\/af9a0a0b9b5aad1b35c4beb97732cb3d?s=90&quot;);\"><\/div>\n<div class=\"embed__caption\">\n<div class=\"embed__caption-title\"><span>dqunbp<\/span><\/div>\n<p><a href=\"https:\/\/dqunbp.vercel.app\/posts\/text-stroke\" target=\"_blank\" rel=\"noopener noreferrer nofollow\" class=\"embed__caption-link\">dqunbp.vercel.app<\/a><\/div>\n<\/div>\n<p><strong>styles\/global.css<\/strong><\/p>\n<pre><code class=\"css\">html, body, #__next {   padding: 0;   margin: 0;   width: 100%;   height: 100%;   font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen,     Ubuntu, Cantarell, \"Open Sans\", \"Helvetica Neue\", sans-serif; }  * {   box-sizing: border-box; }  .app-container {   width: 100%;   height: 100%;   position: relative; }  .map-wrapper, .loading-holder {   position: absolute;   height: 100%;   width: 100%;   top: 0;   left: 0;   bottom: 0;   right: 0; }  .loading-holder {   background: -webkit-linear-gradient(     45deg,     rgba(152, 207, 195, 0.7),     rgb(86, 181, 184)   );   background: -moz-linear-gradient(     45deg,     rgba(152, 207, 195, 0.7),     rgb(86, 181, 184)   );   background: linear-gradient(     45deg,     rgba(152, 207, 195, 0.7),     rgb(86, 181, 184),     0.9   );    display: flex;   justify-content: center;   align-items: center;   flex-direction: column; }  .loading-holder .icon {   transform: scale(2);   fill: rgba(1, 1, 1, 0.7);   animation: pulse 1.5s ease-in-out infinite; }  .loading-holder h1 {   margin-top: 4rem;   text-shadow: 0px 0px 10px rgba(152, 207, 195, 0.7); }  @keyframes pulse {   0% {     transform: scale(2);   }   50% {     transform: scale(2.3);   }   100% {     transform: scale(2);   } } <\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u0438 \u043a\u0430\u0440\u0442\u044b \u043c\u044b \u0443\u0432\u0438\u0434\u0438\u043c \u0441\u0438\u043c\u043f\u0430\u0442\u0438\u0447\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/079\/a7d\/6b3\/079a7d6b39e422118f883d56aaf3f737.gif\" width=\"768\" height=\"443\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/079\/a7d\/6b3\/079a7d6b39e422118f883d56aaf3f737.gif\"\/><\/figure>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/671\/dd4\/afd\/671dd4afdee7e710e9e10c580a93dbe8.jpg\" width=\"768\" height=\"443\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/671\/dd4\/afd\/671dd4afdee7e710e9e10c580a93dbe8.jpg\" data-blurred=\"true\"\/><\/figure>\n<p>\u0421\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u0438 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/p>\n<div class=\"embed_link\">\n<div class=\"embed__thumb\" style=\"background-image: url(&quot;https:\/\/opengraph.githubassets.com\/d867b4055694f0031dd32be92a443ef3120219ebc336db5c4a05d68e8cb18fbb\/dqunbp\/using-mapbox-gl-with-react&quot;);\"><\/div>\n<div class=\"embed__caption\">\n<div class=\"embed__caption-title\"><span>dqunbp\/using-mapbox-gl-with-react<\/span><\/div>\n<p><a href=\"https:\/\/github.com\/dqunbp\/using-mapbox-gl-with-react\" target=\"_blank\" rel=\"noopener noreferrer nofollow\" class=\"embed__caption-link\">github.com<\/a><\/div>\n<\/div>\n<div class=\"embed_link\">\n<div class=\"embed__thumb\" style=\"background-image: url(&quot;https:\/\/og-image.vercel.app\/Using%20**mapbox-gl**%20with%20React%20and%20**Next.js**.png?theme=light&amp;md=1&amp;fontSize=75px&amp;images=https%3A%2F%2Fassets.vercel.com%2Fimage%2Fupload%2Ffront%2Fassets%2Fdesign%2Fnextjs-black-logo.svg&amp;images=https%3A%2F%2Fupload.wikimedia.org%2Fwikipedia%2Fcommons%2Fthumb%2F1%2F1f%2FMapbox_logo_2019.svg%2F1024px-Mapbox_logo_2019.svg.png&amp;widths=350&amp;widths=auto&amp;heights=undefined&amp;heights=100&quot;);\"><\/div>\n<div class=\"embed__caption\">\n<div class=\"embed__caption-title\"><span>Using mapbox-gl with React and Next.js<\/span><\/div>\n<p><a href=\"https:\/\/using-mapbox-gl-with-react.vercel.app\" target=\"_blank\" rel=\"noopener noreferrer nofollow\" class=\"embed__caption-link\">using-mapbox-gl-with-react.vercel.app<\/a><\/div>\n<\/div>\n<h2>\u0425\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430 \u043a\u0430\u0440\u0442\u044b \u0432\u043d\u0435 React<\/h2>\n<p>\u041f\u0440\u043e \u0442\u043e \u043a\u0430\u043a \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043a\u0430\u0440\u0442\u044b <code>mapbox-gl<\/code> \u0432\u043d\u0435 <code>React<\/code> \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u0432 \u0441\u0432\u043e\u0435\u0439 <a href=\"https:\/\/habr.com\/ru\/articles\/569302\/\" rel=\"noopener noreferrer nofollow\">\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a><\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \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\/articles\/565636\/\"> https:\/\/habr.com\/ru\/articles\/565636\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<h2>\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0445\u043e\u0447\u0443 \u043e\u043f\u0438\u0441\u0430\u0442\u044c \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0435 \u043c\u043d\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u043d\u0438\u044f <code>mapbox-gl<\/code> \u0432 <code>React<\/code> \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0433\u043e \u0432\u0435\u0431 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0435\u0433\u043e \u043a\u0430\u0440\u0442\u0443 \u043d\u0430 <code>Next.js<\/code> \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <code>Typescript<\/code>, \u043a\u043e\u0434 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043a\u0430\u0440\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u043b\u044e\u0431\u043e\u043c \u043b\u044e\u0431\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043d\u0430 <code>React<\/code><\/p>\n<p>\u042d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f \u0432\u0445\u043e\u0434\u0438\u0442 \u0432 \u0446\u0438\u043a\u043b \u0441\u0442\u0430\u0442\u0435\u0439<\/p>\n<div class=\"embed_link embed_layout-right\">\n<div class=\"embed__thumb\" style=\"background-image: url(&quot;https:\/\/habr.com\/share\/publication\/565216\/a299fc85e2e5805e0e5c65e16d01028b\/&quot;);\"><\/div>\n<div class=\"embed__caption\">\n<div class=\"embed__caption-title\"><span>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c mapbox-gl \u0432 React<\/span><\/div>\n<div class=\"embed__caption-description\">\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b\u0412 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435 \u043c\u043e\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0432 geoalert.io \u044f \u043d\u0435 \u0440\u0430\u0437 \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u043b\u0441\u044f \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u043e\u0439 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0441\u043e&#8230;<\/div>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/565216\/\" target=\"_blank\" rel=\"noopener noreferrer nofollow\" class=\"embed__caption-link\">habr.com<\/a><\/div>\n<\/div>\n<p>\u042f \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u044e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043a\u0430\u0440\u0442\u044b:<\/p>\n<ul>\n<li>\n<p>\u0418\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0441 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435\u043c \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430 \u043a\u0430\u0440\u0442\u044b \u0432\u043d\u0443\u0442\u0440\u0438 <code>React<\/code> \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430<\/p>\n<\/li>\n<li>\n<p>\u0425\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430 \u043a\u0430\u0440\u0442\u044b \u0432\u043d\u0435 <code>React<\/code><\/p>\n<\/li>\n<\/ul>\n<h2>\u0421\u043f\u0440\u0430\u0432\u043a\u0430 \u043f\u043e \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u0430\u043c \u0441 \u043a\u043e\u0434\u043e\u043c<\/h2>\n<blockquote>\n<p>\u200b\u200b \u0414\u043b\u044f \u043a\u043e\u043c\u0444\u043e\u0440\u0442\u043d\u043e\u0433\u043e \u0447\u0442\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0412\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u043c\u0435\u0442\u044c \u0431\u0430\u0437\u043e\u0432\u044b\u0435 \u0437\u043d\u0430\u043d\u0438\u044f <code>React<\/code>, <code>Typescript<\/code> \u0438 <code>CSS<\/code><\/p>\n<\/blockquote>\n<blockquote>\n<p>\u200b\u200b \u0412\u0441\u0435 \u0441\u043d\u0438\u043f\u043f\u0435\u0442\u044b \u0441 \u043a\u043e\u0434\u043e\u043c \u0431\u0443\u0434\u0443\u0442 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c <code>Typescript<\/code>, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0438\u043f\u0438\u0437\u0430\u0446\u0438\u0438 \u0432 javascript \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0443\u0447\u0448\u0435\u0439 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u043e\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u044f \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0438\u0430\u043b\u044c\u043d\u043e \u0435\u0435 \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0441\u044c \u0442\u0430\u043c \u0433\u0434\u0435 \u044d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043f\u0440\u043e\u0448\u0443 \u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u0435\u0441\u043b\u0438 \u0432\u044b \u0435\u0435 \u043d\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u044b \u0441 \u043d\u0438\u043c, <a href=\"https:\/\/egghead.io\/courses\/up-and-running-with-typescript\" rel=\"noopener noreferrer nofollow\">\u0432\u043e\u0442 \u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u0443\u0440\u0441 \u043e\u0442 egghead.io \u0433\u0434\u0435 \u0432\u044b \u0441\u043c\u043e\u0436\u0435\u0442\u0435 \u0441 \u043d\u0438\u043c \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0442\u044c\u0441\u044f<\/a> <\/p>\n<\/blockquote>\n<blockquote>\n<p>\u200b\u200b \u042f \u043f\u0440\u0435\u0434\u043f\u043e\u0447\u0438\u0442\u0430\u044e \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c <code>React<\/code> \u043a\u0430\u043a <code>import * as React from \"react\"<\/code> \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u0431 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u0432 <a href=\"https:\/\/epicreact.dev\/importing-react-through-the-ages\/\" rel=\"noopener noreferrer nofollow\">\u0437\u0430\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0430\u0440\u0442\u0438\u043a\u043b\u0435 \u043e\u0442  Kent C. Dodds<\/a><\/p>\n<\/blockquote>\n<blockquote>\n<p>\u200b\u200b \u0415\u0441\u043b\u0438 \u0432 \u043a\u043e\u0434\u0435 \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u0435\u0442\u0441\u044f <code>\/\/ ...<\/code> \u044d\u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0447\u0438\u0442\u0430\u0442\u044c \u043a\u0430\u043a \u043c\u0435\u0441\u0442\u0430 \u0441 \u043f\u0440\u043e\u043f\u0443\u0449\u0435\u043d\u043d\u044b\u043c \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u043c\u0441\u044f \u043a\u043e\u0434\u043e\u043c<\/p>\n<\/blockquote>\n<h2>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f<\/h2>\n<p>\u041f\u0440\u0435\u0436\u0434\u0435 \u0432\u0441\u0435\u0433\u043e \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442 \u043d\u0430 <code>Next.js<\/code> \u043f\u043e \u0448\u0430\u0431\u043b\u043e\u043d\u0443 <code>Typescript<\/code><\/p>\n<pre><code class=\"bash\">npx create-next-app --typescript my-awesome-app<\/code><\/pre>\n<p>\u041e\u0442\u043a\u0440\u043e\u0435\u043c \u043f\u0430\u043f\u043a\u0443 \u043f\u0440\u043e\u0435\u043a\u0442\u0430 \u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u0442\u0430\u043a \u0436\u0435 <code>mapbox-gl<\/code> \u0441 \u0442\u0438\u043f\u0430\u043c\u0438 \u0434\u043b\u044f <code>Typescript<\/code><\/p>\n<pre><code class=\"bash\">cd my-awesome-app  npm install --save mapbox-gl &amp;&amp; npm install -D @types\/mapbox-gl<\/code><\/pre>\n<p>\u0422\u0430\u043a \u0436\u0435 \u043d\u0430\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f <a href=\"https:\/\/docs.mapbox.com\/help\/getting-started\/access-tokens\/\" rel=\"noopener noreferrer nofollow\">accessToken<\/a> \u0434\u043b\u044f <code>mapbox-gl<\/code> \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u0435\u0433\u043e \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0435\u0433\u043e \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 \u043a\u043e\u0434\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/p>\n<pre><code class=\"bash\">touch .env.local  echo NEXT_PUBLIC_MAPBOX_TOKEN=&lt;\u0432\u0430\u0448_\u0442\u043e\u043a\u0435\u043d> >> .env.local<\/code><\/pre>\n<p>\u0422\u0430\u043a \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0432\u0430\u0448 \u0444\u0430\u0439\u043b \u0441 <a href=\"https:\/\/nextjs.org\/docs\/basic-features\/environment-variables\" rel=\"noopener noreferrer nofollow\">\u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f <\/a><code>Next.js<\/code><\/p>\n<p><strong>.env.local<\/strong><\/p>\n<pre><code class=\"bash\">NEXT_PUBLIC_MAPBOX_TOKEN=&lt;\u0432\u0430\u0448_\u0442\u043e\u043a\u0435\u043d><\/code><\/pre>\n<h2>\u0418\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u0432 \u0432\u0438\u0434\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 React<\/h2>\n<h3>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0441\u0442\u0438\u043b\u0435\u0439<\/h3>\n<p>\u0423\u0434\u0430\u043b\u0438\u043c \u043b\u0438\u0448\u043d\u0438\u0435 \u0441\u0442\u0438\u043b\u0438 \u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u043c \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0441\u0442\u0438\u043b\u0435\u0439<\/p>\n<pre><code class=\"bash\">rm styles\/Home.module.css<\/code><\/pre>\n<p><strong>styles\/global.css<\/strong><\/p>\n<pre><code class=\"css\">html, body, #__next {   padding: 0;   margin: 0;   width: 100%;   height: 100%; }  * {   box-sizing: border-box; } <\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432\u044b\u0441\u043e\u0442\u0430 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0440\u0430\u0432\u043d\u044f\u043b\u0430\u0441\u044c <code>100%<\/code> \u0432\u044b\u0441\u043e\u0442\u044b \u043e\u043a\u043d\u0430, \u0437\u0430\u0434\u0430\u0434\u0438\u043c \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 <code>width<\/code> \u0438 <code>height<\/code> \u0440\u0430\u0432\u043d\u044b\u0435 <code>100%<\/code> \u0434\u043b\u044f <code>html<\/code> \u0438 <code>body<\/code> <\/p>\n<p>\u0412\u044b\u0441\u043e\u0442\u0443 \u0442\u0430\u043a \u0436\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0434\u043b\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0441 <code>css<\/code> \u0441\u0435\u043b\u0435\u043a\u0442\u043e\u0440\u043e\u043c <code>#__next<\/code> \u0442\u0430\u043a \u043a\u0430\u043a \u0432 <code>Next.js<\/code> \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043a\u043e\u0440\u043d\u0435\u0432\u044b\u043c \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u043c \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f <code>&lt;div id=\"__next\">...&lt;\/div><\/code><\/p>\n<h3>\u041f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043a\u0430\u0440\u0442\u044b<\/h3>\n<p><strong>components\/mapbox-map.tsx<\/strong><\/p>\n<pre><code class=\"java\">import * as React from \"react\"; import mapboxgl from \"mapbox-gl\"; import \"mapbox-gl\/dist\/mapbox-gl.css\";  \/\/ \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0441\u0442\u0438\u043b\u0438 mapbox-gl \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0440\u0442\u0430 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u043b\u0430\u0441\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u043d\u043e  function MapboxMap() {     \/\/ \u0437\u0434\u0435\u0441\u044c \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043a\u0430\u0440\u0442\u044b \u043f\u043e\u0441\u043b\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438   const [map, setMap] = React.useState&lt;mapboxgl.Map>();    \/\/ React ref \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u0441\u044b\u043b\u043a\u0438 \u043d\u0430 DOM \u043d\u043e\u0434\u0443 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442    \/\/ \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 `container`    \/\/ \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u0430\u0440\u0442\u044b `mapbox-gl`   \/\/ \u043f\u043e-\u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c `null`     const mapNode = React.useRef(null);    React.useEffect(() => {     const node = mapNode.current;         \/\/ \u0435\u0441\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442 window \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d,         \/\/ \u0442\u043e \u0435\u0441\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u0441\u044f \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435         \/\/ \u0438\u043b\u0438 dom node \u043d\u0435 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u0430, \u0442\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c     if (typeof window === \"undefined\" || node === null) return;      \/\/ \u0438\u043d\u0430\u0447\u0435 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043a\u0430\u0440\u0442\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u044f \u0435\u043c\u0443 \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 DOM \u043d\u043e\u0434\u0443     \/\/ \u0430 \u0442\u0430\u043a\u0436\u0435 accessToken \u0434\u043b\u044f mapbox     const mapboxMap = new mapboxgl.Map({       container: node,             accessToken: process.env.NEXT_PUBLIC_MAPBOX_TOKEN,             style: \"mapbox:\/\/styles\/mapbox\/streets-v11\",       center: [-74.5, 40],       zoom: 9,     });      \/\/ \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u0430\u0440\u0442\u044b \u0432 React.useState     setMap(mapboxMap);          \/\/ \u0447\u0442\u043e\u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0443\u0442\u0435\u0447\u043a\u0438 \u043f\u0430\u043c\u044f\u0442\u0438 \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043a\u0430\u0440\u0442\u044b \/\/ \u043a\u043e\u0433\u0434\u0430 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u0434\u0435\u043c\u043e\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d     return () => {       mapboxMap.remove();     };   }, []);      return &lt;div ref={mapNode} style={{ width: \"100%\", height: \"100%\" }} \/>; }  export default MapboxMap <\/code><\/pre>\n<p>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <code>mapbox-gl<\/code> \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 <\/p>\n<div class=\"embed_link\">\n<div class=\"embed__thumb\" style=\"background-image: url(&quot;https:\/\/static-assets.mapbox.com\/branding\/social\/social-1200x630.v2.jpg&quot;);\"><\/div>\n<div class=\"embed__caption\">\n<div class=\"embed__caption-title\"><span>Map | Mapbox GL JS<\/span><\/div>\n<p><a href=\"https:\/\/docs.mapbox.com\/mapbox-gl-js\/api\/map\/\" target=\"_blank\" rel=\"noopener noreferrer nofollow\" class=\"embed__caption-link\">docs.mapbox.com<\/a><\/div>\n<\/div>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \u0432 \u0433\u043b\u0430\u0432\u043d\u0443\u044e \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043c \u043f\u0440\u043e\u0435\u043a\u0442<\/p>\n<p><strong>pages\/index.tsx<\/strong><\/p>\n<pre><code class=\"java\">import MapboxMap from \"..\/components\/mapbox-map\";  function App() {   return &lt;MapboxMap \/>; }  export default App; <\/code><\/pre>\n<pre><code class=\"bash\">npm run dev<\/code><\/pre>\n<p>\u041e\u0442\u043a\u0440\u044b\u0432 <a href=\"http:\/\/localhost:3000\" rel=\"noopener noreferrer nofollow\">http:\/\/localhost:3000<\/a> \u0432\u0438\u0434\u0438\u043c \u043f\u043e\u043b\u043d\u043e\u044d\u043a\u0440\u0430\u043d\u043d\u0443\u044e \u0432\u0435\u0431-\u043a\u0430\u0440\u0442\u0443<\/p>\n<figure class=\"full-width\"><\/figure>\n<h3>\u0427\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043b\u0443\u0447\u0448\u0435<\/h3>\n<p>\u0412 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0445 \u0444\u0438\u0447\u0435\u0439<\/p>\n<ul>\n<li>\n<p><strong>\u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u0430\u0440\u0442\u044b<\/strong> &#8212; \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u043a\u0430\u0440\u0442\u044b \u043b\u043e\u0433\u0438\u0447\u043d\u044b\u043c \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0438\u043c\u0435\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0442\u044c \u0435\u043c\u0443 \u0447\u0435\u0440\u0435\u0437 <code>props<\/code> \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043a\u0430\u0440\u0442\u044b<\/p>\n<\/li>\n<li>\n<p>\u0414<strong>\u043e\u0441\u0442\u0443\u043f \u043a \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0443 \u043a\u0430\u0440\u0442\u044b \u0438\u0437 \u0434\u0440\u0443\u0433\u0438\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 &#8212; \u043f<\/strong>\u043e\u043c\u0438\u043c\u043e \u0441\u0430\u043c\u043e\u0439 \u0432\u0435\u0431-\u043a\u0430\u0440\u0442\u044b \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f \u0434\u0440\u0443\u0433\u0438\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u043c\u0435\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u043a \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0443 \u043a\u0430\u0440\u0442\u044b<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u043e\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043e \u0433\u043e\u0442\u043e\u0432\u043d\u043e\u0441\u0442\u0438 \u043a\u0430\u0440\u0442\u044b<\/strong> &#8212; \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043a\u0430\u0440\u0442\u044b \u0437\u0430\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f, \u043f\u043e\u043a\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0436\u0438\u0434\u0430\u0435\u0442 \u043e\u0442\u043a\u0440\u044b\u0442\u0438\u044f \u043a\u0430\u0440\u0442\u044b,  \u0434\u043b\u044f \u0443\u043b\u0443\u0447\u0448\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043e\u043f\u044b\u0442\u0430, \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0441\u043a\u0435\u043b\u0435\u0442\u043e\u043d \u0438\u043b\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d \u0441\u043e \u0441\u043f\u0438\u043d\u043d\u0435\u0440\u043e\u043c. \u0414\u043b\u044f \u044d\u0442\u0438\u0445 \u0446\u0435\u043b\u0435\u0439 \u0431\u044b\u043b\u043e \u0431\u044b \u0443\u0434\u043e\u0431\u043d\u043e \u0438\u043c\u0435\u0442\u044c \u043a\u043e\u043b\u043b\u0431\u0435\u043a \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0449\u0438\u0439 \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e \u043a\u0430\u043a \u043a\u0430\u0440\u0442\u0430 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0441 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 \u043a\u0430\u0440\u0442\u044b \u0432 \u043c\u043e\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 <a href=\"https:\/\/app.mapflow.ai\" rel=\"noopener noreferrer nofollow\">https:\/\/app.mapflow.ai<\/a><\/p>\n<figure class=\"full-width\"><\/figure>\n<figure class=\"full-width\"><\/figure>\n<h2>\u0423\u043b\u0443\u0447\u0448\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043a\u0430\u0440\u0442\u044b<\/h2>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u043c \u0432\u0441\u0435 \u044d\u0442\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438, \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0434\u043e\u0431\u0430\u0432\u0438\u043c <code>props<\/code> \u0434\u043b\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430 \u0432\u0435\u0431-\u043a\u0430\u0440\u0442\u044b<\/p>\n<pre><code class=\"java\">interface MapboxMapProps {   initialOptions?: Omit&lt;mapboxgl.MapboxOptions, \"container\">;   onCreated?(map: mapboxgl.Map): void;   onLoaded?(map: mapboxgl.Map): void;   onRemoved?(): void; }  function MapboxMap({   initialOptions = {},   onCreated,   onLoaded,   onRemoved, }: MapboxMapProps) {     \/\/ ... <\/code><\/pre>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 <code>props<\/code><\/p>\n<ul>\n<li>\n<p><strong>initialOptions<\/strong> &#8212; <a href=\"https:\/\/www.notion.so\/mapbox-gl-React-Next-js-fac7c457b2da4d0aa8a0a2579e7e10c8\" rel=\"noopener noreferrer nofollow\">\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u0430\u0440\u0442\u044b<\/a>, \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>container<\/code> \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <code>MapboxOptions<\/code> \u0432 \u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/utility-types.html\" rel=\"noopener noreferrer nofollow\">\u0443\u0442\u0438\u043b\u0438\u0442\u0430\u0440\u043d\u044b\u0439 \u0442\u0438\u043f <\/a><code>Omit<\/code><\/p>\n<\/li>\n<li>\n<p><strong>onCreated<\/strong> &#8212; \u043a\u043e\u043b\u043b\u0431\u0435\u043a \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u043f\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044e \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430 \u043a\u0430\u0440\u0442\u044b<\/p>\n<\/li>\n<li>\n<p><strong>onLoaded<\/strong> &#8212; \u043a\u043e\u043b\u043b\u0431\u0435\u043a \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u043f\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044e \u043f\u043e\u043b\u043d\u043e\u0439 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043a\u0430\u0440\u0442\u044b<\/p>\n<\/li>\n<li>\n<p><strong>onRemoved<\/strong> &#8212; \u043a\u043e\u043b\u043b\u0431\u0435\u043a \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c\u044b\u0439 \u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u0430 \u043a\u0430\u0440\u0442\u044b<\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u0432\u043e\u0439\u0441\u0442\u0432\u043e <code>container<\/code> \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 <code>MapboxOptions<\/code> \u0432 \u0434\u0430\u043d\u043d\u043e\u043c\u0443 \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f, \u0447\u0442\u043e\u0431\u044b \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <a href=\"https:\/\/www.typescriptlang.org\/docs\/handbook\/utility-types.html\" rel=\"noopener noreferrer nofollow\">\u0443\u0442\u0438\u043b\u0438\u0442\u0430\u0440\u043d\u044b\u0439 \u0442\u0438\u043f <\/a><code>Omit<\/code><\/p>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0434\u0438\u043c <code>initialOptions<\/code> \u0432 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0432\u0435\u0431-\u043a\u0430\u0440\u0442\u044b, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <a href=\"https:\/\/developer.mozilla.org\/ru\/docs\/Web\/JavaScript\/Reference\/Operators\/Spread_syntax#spread_%D0%B2_%D0%BB%D0%B8%D1%82%D0%B5%D1%80%D0%B0%D0%BB%D0%B0%D1%85_%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%B0\" rel=\"noopener noreferrer nofollow\">spread syntax<\/a>, \u0442\u0430\u043a \u0436\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043a\u0430\u0440\u0442\u044b, \u0435\u0441\u043b\u0438 \u043a\u043e\u043b\u043b\u0431\u0435\u043a <code>onMapLoaded<\/code>, \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0435\u0441\u043b\u0438 \u043e\u043d \u0431\u044b\u043b \u043f\u0435\u0440\u0435\u0434\u0430\u043d \u0432 <code>props<\/code> \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430, \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0434\u043b\u044f <code>onMapRemoved<\/code><\/p>\n<pre><code class=\"java\">\/\/ ...     const mapboxMap = new mapboxgl.Map({       container: node,       accessToken: process.env.NEXT_PUBLIC_MAPBOX_TOKEN,       style: \"mapbox:\/\/styles\/mapbox\/streets-v11\",       center: [-74.5, 40],       zoom: 9,       ...initialOptions,     });      setMap(mapboxMap);     if (onCreated) onCreated(mapboxMap)  \/\/ \u0435\u0441\u043b\u0438 onLoaded \u0443\u043a\u0430\u0437\u0430\u043d, \u043e\u043d \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u0432\u0430\u043d \u0435\u0434\u0438\u043d\u043e\u0436\u0434\u044b     \/\/ \u043f\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043a\u0430\u0440\u0442\u044b if (onLoaded) mapboxMap.once(\"load\", () => onLoaded(mapboxMap));  return () => {       mapboxMap.remove();       setMap(undefined);       if (onRemoved) onRemoved();     };      \/\/ eslint-disable-next-line react-hooks\/exhaustive-deps   }, []);  \/\/ ...<\/code><\/pre>\n<p>\u0422\u0443\u0442 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439 \u0434\u043b\u044f \u043b\u0438\u043d\u0442\u0435\u0440\u0430 <\/p>\n<pre><code class=\"javascript\">\/\/ eslint-disable-next-line react-hooks\/exhaustive-deps<\/code><\/pre>\n<p>\u0421\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u043e\u0431\u0449\u0435\u043f\u0440\u0438\u043d\u044f\u0442\u043e\u043c\u0443 \u043f\u0440\u0430\u0432\u0438\u043b\u0443 <code>react-hooks\/exhaustive-deps<\/code> \u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u043b\u0438 \u0443\u043a\u0430\u0437\u0430\u0442\u044c \u0432 \u0441\u043f\u0438\u0441\u043a\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u0434\u043b\u044f <code>React.useEffect<\/code> \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 \u0432 \u0445\u0443\u043a \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 <code>[initialOptions, onMapLoaded, onMapRemoved]<\/code><\/p>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u0430\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439 \u043f\u0443\u0441\u0442\u044b\u043c, \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043d\u0435 \u043f\u0435\u0440\u0435\u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043a\u0430\u0440\u0442\u044b \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0435\u0441\u043b\u0438 <code>initialOptions<\/code> \u0438\u043b\u0438 <code>onMapLoaded<\/code> \u0438\u0437\u043c\u0435\u043d\u044f\u0442\u0441\u044f, \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 <code>React.useEffect<\/code> \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0447\u0438\u0442\u0430\u0442\u044c \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435 \u043d\u0438\u0436\u0435<\/p>\n<div class=\"embed_link\">\n<div class=\"embed__thumb\" style=\"background-image: url(&quot;undefined&quot;);\"><\/div>\n<div class=\"embed__caption\">\n<div class=\"embed__caption-title\"><span>A Complete Guide to useEffect<\/span><\/div>\n<p><a href=\"https:\/\/overreacted.io\/a-complete-guide-to-useeffect\/\" target=\"_blank\" rel=\"noopener noreferrer nofollow\" class=\"embed__caption-link\">overreacted.io<\/a><\/div>\n<\/div>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0442\u0430\u043a<\/p>\n<p><strong>components\/mapbox-map.tsx<\/strong><\/p>\n<pre><code class=\"java\">import * as React from \"react\"; import mapboxgl from \"mapbox-gl\"; import \"mapbox-gl\/dist\/mapbox-gl.css\";  interface MapboxMapProps {   initialOptions?: Omit&lt;mapboxgl.MapboxOptions, \"container\">;   onCreated?(map: mapboxgl.Map): void;   onLoaded?(map: mapboxgl.Map): void;   onRemoved?(): void; }  function MapboxMap({   initialOptions = {},   onCreated,   onLoaded,   onRemoved, }: MapboxMapProps) {   const [map, setMap] = React.useState&lt;mapboxgl.Map>();    const mapNode = React.useRef(null);    React.useEffect(() => {     const node = mapNode.current;      if (typeof window === \"undefined\" || node === null) return;      const mapboxMap = new mapboxgl.Map({       container: node,       accessToken: process.env.NEXT_PUBLIC_MAPBOX_TOKEN,       style: \"mapbox:\/\/styles\/mapbox\/streets-v11\",       center: [-74.5, 40],       zoom: 9,       ...initialOptions,     });      setMap(mapboxMap);     if (onCreated) onCreated(mapboxMap);      if (onLoaded) mapboxMap.once(\"load\", () => onLoaded(mapboxMap));      return () => {       mapboxMap.remove();       setMap(undefined);       if (onRemoved) onRemoved();     };      \/\/ eslint-disable-next-line react-hooks\/exhaustive-deps   }, []);    return &lt;div ref={mapNode} style={{ width: \"100%\", height: \"100%\" }} \/>; }  export default MapboxMap;<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0435\u0440\u0435\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430 \u043f\u0440\u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0438 \u043a\u0430\u0440\u0442\u044b \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043b\u043b\u0431\u0435\u043a <code>onMapLoaded<\/code> \u043f\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044e \u0435\u0435 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u0422\u0430\u043a \u0436\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>onMapLoaded<\/code> \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043a\u0430\u0440\u0442\u044b \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u0432 \u0440\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0435. \u0422\u0430\u043a \u0436\u0435 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>onMapRemoved<\/code> \u0435\u0441\u043b\u0438 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0437\u043d\u0430\u0442\u044c \u0447\u0442\u043e \u0438\u043d\u0441\u0442\u0430\u043d\u0441 \u043a\u0430\u0440\u0442\u044b \u0431\u044b\u043b \u0443\u0434\u0430\u043b\u0435\u043d.<\/p>\n<p>\u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u044d\u0442\u0438\u043c, \u0443\u043a\u0430\u0436\u0435\u043c \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0446\u0435\u043d\u0442\u0440\u0430 \u043a\u0430\u0440\u0442\u044b, \u0430 \u0442\u0430\u043a \u0436\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043a\u0430\u0440\u0442\u044b.<\/p>\n<p>\u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 <code>MapLoadingHolder<\/code> \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f \u043f\u043e\u0432\u0435\u0440\u0445 \u043a\u0430\u0440\u0442\u044b \u043f\u043e\u043a\u0430 \u043e\u043d\u0430 \u043d\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d\u0430.<\/p>\n<p>\u0414\u043b\u044f \u044d\u043a\u0440\u0430\u043d\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u0430\u043c \u0442\u0430\u043a \u0436\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 <code>svg<\/code> \u0438\u043a\u043e\u043d\u043a\u0430, \u044f \u0435\u0435 \u0441 <a href=\"https:\/\/www.freepik.com\" rel=\"noopener noreferrer nofollow\">Freepic<\/a>, \u043f\u0440\u0435\u0434\u0432\u0430\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0432 \u0435\u0435 \u0432 jsx \u0444\u043e\u0440\u043c\u0430\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <a href=\"https:\/\/svg2jsx.com\/\" rel=\"noopener noreferrer nofollow\">https:\/\/svg2jsx.com\/<\/a><\/p>\n<p><strong>components\/world-icon.tsx<\/strong><\/p>\n<pre><code class=\"java\">function WorldIcon({ className = \"\" }: { className?: string }) {   return (     &lt;svg       className={className}       xmlns=\"http:\/\/www.w3.org\/2000\/svg\"       width=\"48.625\"       height=\"48.625\"    <\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\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-412496","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/412496","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=412496"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/412496\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=412496"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=412496"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=412496"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}