React
Warning
Supported React version: 16 or higher.
There is a React analog for every imperative API class inherited from YMapEntity. To use the React API version, connect the @yandex/ymaps3-reactify module:
const ymaps3Reactify = await ymaps3.import('@yandex/ymaps3-reactify');
const reactify = ymaps3Reactify.reactify.bindTo(React, ReactDOM);
const {YMap, YMapDefaultSchemeLayer, YMapDefaultFeaturesLayer, YMapMarker} = reactify.module(ymaps3);
Note
The @yandex/ymaps3-reactify module provides a set of React access methods both for individual objects and modules/packages as a whole. The hierarchy of objects and initialization parameters are the same for most classes.
After connecting the module, use YMapEntity descendant objects as React components:
<YMap location={{center: [37.588144, 55.733842], zoom: 9}} mode="vector">
<YMapDefaultSchemeLayer />
<YMapDefaultFeaturesLayer />
<YMapMarker coordinates={[25.229762, 55.289311]} draggable={true}>
<section>
<h1>You can drag this header</h1>
</section>
</YMapMarker>
</YMap>
Note
The JS API supports integration only with React JS.
React Native is currently not supported.
Quick start
Connecting via top-level-await
<!DOCTYPE html>
<html>
<head>
<!-- Replace YOUR_API_KEY with the real key -->
<script src="https://api-maps.yandex.ru/v3/?apikey=YOUR_API_KEY&lang=en_US"></script>
</head>
<body>
<div id="root"></div>
</body>
</html>
import ReactDOM from 'react-dom/client';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(<App />);
import {YMap, YMapDefaultSchemeLayer, YMapDefaultFeaturesLayer, YMapMarker, reactify} from './lib/ymaps3';
import type {YMapLocationRequest} from 'ymaps3';
const LOCATION: YMapLocationRequest = {
center: [37.588144, 55.733842],
zoom: 9
};
export default function App() {
return (
<div style={{width: '600px', height: '400px'}}>
<YMap location={reactify.useDefault(LOCATION)}>
<YMapDefaultSchemeLayer />
<YMapDefaultFeaturesLayer />
<YMapMarker coordinates={reactify.useDefault([37.588144, 55.733842])} draggable={true}>
<section>
<h1>You can drag this header</h1>
</section>
</YMapMarker>
</YMap>
</div>
);
}
import React from 'react';
import ReactDom from 'react-dom';
const [ymaps3React] = await Promise.all([ymaps3.import('@yandex/ymaps3-reactify'), ymaps3.ready]);
export const reactify = ymaps3React.reactify.bindTo(React, ReactDom);
export const {YMap, YMapDefaultSchemeLayer, YMapDefaultFeaturesLayer, YMapMarker} = reactify.module(ymaps3);
{
"compilerOptions": {
"target": "es2017",
"lib": ["dom", "dom.iterable", "esnext"],
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"jsx": "react-jsx",
"typeRoots": ["./node_modules/@types", "./node_modules/@yandex/ymaps3-types"],
"paths": {
"ymaps3": ["./node_modules/@yandex/ymaps3-types"]
}
}
}
{
"devDependencies": {
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"@yandex/ymaps3-types": "^0.0.17",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-scripts": "5.0.1",
"typescript": "^4.9.5"
},
"scripts": {
"start": "react-scripts start"
}
}
Set dependencies and run a local server:
npm install
npm start
Open the app
Specifics
-
In
package.json, add a dev dependency on the@yandex/ymaps3-typespackage.We recommend installing the latest version:
npm i --save-dev @yandex/ymaps3-types@latest -
In
tsconfig.json, setcompilerOptions.typeRootswith a list of paths to type files. Add a path to the@yandex/ymaps3-typespackage there to make theymaps3namespace with types appear in the global scope.Note
The
ymaps3namespace contains all the class types provided by the JS API, but they are not available in the runtime environment untilymaps3.readyis resolved. -
In
tsconfig.json, setcompilerOptions.paths, informing the TS compiler that the contents of the importedymaps3package should be searched for at the specified path. This enables you to import types in project files as if they were located not at@yandex/ymaps3-types, but in theymaps3package:import type {YMapLocationRequest} from 'ymaps3';All types must be imported from the root.
The internal structure isn't guaranteed and can change over time.
-
In
tsconfig.json, for top-level-await to operate correctly, thecompilerOptions.moduleparameter must be set to one of the following values:es2022,esnext,system, orpreserve. ThecompilerOptions.targetparameter must be set toes2017or higher. -
Connect the
@yandex/ymaps3-reactifymodule. Inlib/ymaps3.ts, wait until the JS API and Reactify module are fully loaded and then export the necessary map components so that they can be used in other parts of the project:import React from 'react'; import ReactDom from 'react-dom'; const [ymaps3React] = await Promise.all([ymaps3.import('@yandex/ymaps3-reactify'), ymaps3.ready]); export const reactify = ymaps3React.reactify.bindTo(React, ReactDom); export const {YMap, YMapDefaultSchemeLayer, YMapDefaultFeaturesLayer} = reactify.module(ymaps3);Note
The
@yandex/ymaps3-reactifymodule provides a set of React access methods both for individual objects and modules/packages as a whole. The hierarchy of objects and initialization parameters are the same. -
The use of top-level-await in
lib/ymaps3.tsguarantees thatymaps3.readyandymaps3.import('@yandex/ymaps3-reactify')are executed before the map components are imported, allowing any JS API objects to be used as React components synchronously:<YMap location={reactify.useDefault(LOCATION)}> <YMapDefaultSchemeLayer /> <YMapDefaultFeaturesLayer /> ... </YMap>
reactify.useDefault
YMap and all other components are uncontrolled. Components use the imperative interface of the library (for example, YMapZoomControl calls YMap.update({location})). This may cause desynchronizing with the state and parameters in React (for example, location for YMap or coordinates for YMapMarker with dragging enabled).
Use reactify.useDefault(value) to set a component parameter only once and not update it on re-renders. For example, <YMap location={reactify.useDefault({center, zoom})}/> will behave as <input defaultValue={''}/>.
To control parameter updates, use the second reactify.useDefault(value, deps) parameter: an array of dependencies as in React hooks (for example, useCallback, useMemo, useEffect). The parameter will be updated if the dependency array is different.
For parameters with objects, the value itself can be used as a dependency. Re-rendering occurs only if the values are different. For example, const [location, setLocation] = useState(...), reactify.useDefault(location, [location]), setLocation({...}).
reactify.useDefault works with any parameters of any components from reactify.
Warning
reactify.useDefault returns an object with no public contract and should be used only directly in component parameters.
Custom implementations of ymaps3.YMapEntity objects for React
Use the ymaps3.overrideKeyReactify key to determine custom implementations of ymaps3.YMapEntity objects for reactify:
type YMapSomeClassProps = {
id: string;
};
export class YMapSomeClass extends ymaps3.YMapComplexEntity<YMapSomeClassProps> {
static [ymaps3.overrideKeyReactify] = YMapSomeClassReactifyOverride;
//...
}
and the method for determining a custom implementation:
export const YMapSomeClassReactifyOverride = (
YMapSomeClassI, // base YMapSomeClass class
{reactify, React}
) => {
const YMapSomeClassReactified = reactify.entity(YMapSomeClassI); // Standard reactify method
const YMapSomeClassR = React.forwardRef((props, ref) => {
return (<>
<YMapSomeClassReactified {...props} ref={ref} ... />
</>);
})
return YMapSomeClassR;
}
and add the resulting component to the app:
import {YMapSomeClass} from './some-class';
import React from 'react';
import ReactDOM from 'react-dom';
// ...
const ymaps3Reactify = await ymaps3.import('@yandex/ymaps3-reactify');
const reactify = ymaps3Reactify.reactify.bindTo(React, ReactDOM);
const YMapSomeClassR = reactify.entity(YMapSomeClass);
function App() {
return <YMapSomeClassR id="some_id" />;
}
An open-source JavaScript library for creating application UIs.
An open-source JavaScript framework that came after React JS. It is used to develop mobile and web applications.