Интеграция с Next.js
Данная статья описывает интеграцию с App Router Next.js версии 13 и выше.
Примечание
Интеграция с Next.js основана на использовании модуля @yandex/ymaps3-reactify.
Перед прочтением данной статьи, рекомендуем ознакомиться с интеграцией с React JS.
Шаг 1. Подключение API
Для начала необходимо подключить API с помощью компонента <Script />:
import Script from 'next/script';
export default function RootLayout({children}) {
return (
<html>
<body>
{children}
<Script src="https://api-maps.yandex.ru/v3/?apikey=YOUR_API_KEY&lang=ru_RU" strategy="beforeInteractive" />
);
}
Важно
Важно указать стратегию загрузки скрипта beforeInteractive.
Это позволит загрузить API до того, как Next.js начнет гидрацию страницы.
Шаг 2. Подключение модуля @yandex/ymaps3-reactify
В App Router каждая страница является серверным компонентом, код которого не выполняется в браузере.
Создадим компонент Map и добавим директиву use client, чтобы код компонента выполнялся в браузере.
'use client';
const Map = () => {
return null;
};
export default Map;
Теперь код компонента выполняется дважды: в браузере и на сервере.
Модуль @yandex/ymaps3-reactify не поддерживает серверный рендеринг.
Для того, чтобы модуль загружался только в браузере, используем React.useEffect.
'use client';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
const Map = () => {
const [reactifiedApi, setReactifiedApi] = React.useState();
React.useEffect(() => {
Promise.all([
ymaps3.import('@yandex/ymaps3-reactify'),
ymaps3.ready
]).then(([{reactify}]) =>
setReactifiedApi(reactify.bindTo(React, ReactDOM).module(ymaps3))
);
}, []);
return null;
};
export default Map;
Теперь мы можем использовать @yandex/ymaps3-reactify для рендеринга карты.
'use client';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
const Map = () => {
const [reactifiedApi, setReactifiedApi] = React.useState();
React.useEffect(() => {
Promise.all([
ymaps3.import('@yandex/ymaps3-reactify'),
ymaps3.ready
]).then(([{reactify}]) =>
setReactifiedApi(reactify.bindTo(React, ReactDOM).module(ymaps3))
);
}, []);
if (!reactifiedApi) {
return null;
}
const {YMap, YMapDefaultSchemeLayer, YMapDefaultFeaturesLayer} = reactifiedApi;
return (
<YMap location={{center: [37.588144, 55.733842], zoom: 9}}>
<YMapDefaultSchemeLayer />
<YMapDefaultFeaturesLayer />
</YMap>
);
};
export default Map;
'use client';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import {ReactifiedModule} from '@yandex/ymaps3-types/reactify/reactify';
import {LOCATION} from '../variables';
type ReactifiedApi = ReactifiedModule<typeof ymaps3>;
const Map = () => {
const [reactifiedApi, setReactifiedApi] = React.useState<ReactifiedApi>();
React.useEffect(() => {
Promise.all([
ymaps3.import('@yandex/ymaps3-reactify'),
ymaps3.ready
]).then(([{reactify}]) =>
setReactifiedApi(reactify.bindTo(React, ReactDOM).module(ymaps3))
);
}, []);
if (!reactifiedApi) {
return null;
}
const {YMap, YMapDefaultSchemeLayer, YMapDefaultFeaturesLayer} = reactifiedApi;
return (
<YMap location={LOCATION}>
<YMapDefaultSchemeLayer />
<YMapDefaultFeaturesLayer />
</YMap>
);
};
export default Map;
import * as React from 'react';
import Script from 'next/script';
import Map from '@/components/map';
export default function Home() {
return (
<>
<Script
src="https://api-maps.yandex.ru/v3/?apikey=YOUR_API_KEY&lang=ru_RU"
strategy="beforeInteractive"
/>
);
}
import * as React from 'react';
export default function RootLayout({
children
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html>
<body style={{padding: 0, margin: 0}}>
{children}
</body>
</html>
);
}
import type {YMapLocationRequest} from '@yandex/ymaps3-types';
export const LOCATION: YMapLocationRequest = {
center: [37.623082, 55.75254], // starting position [lng, lat]
zoom: 9 // starting zoom
};