Skip to main content

Core Principles

Modular Approach

This library heavily utilizes Yandex.Maps API module system to make amount of downloaded and executed code from Yandex.Maps as minimal as possible. There are some pros and cons to this system and there are also a way to opt out of this completely.

By default, this library will download only the modules that are actually rendered on the page. If <Placemark /> or <ObjectManager /> is not mounted in the page, corresponding would not be downloaded.

That means that the amount of code your clients will download and execute will be as minimal as possible. On the other hand that means that instead of getting a lot of familiar Yandex.Maps API modules by default, now you need to really think about what you are using on the page.

In the example below, we are mounting Map with a Placemark on the page:

You can notice that all map controls that are usually provided on the map by default are missing here. This is happening because they are not part of the "core" Yandex.Maps module, not they are part of the Map or Placemark module.

Loading Modules with modules Prop

Let's fix this by specifying which controls we want exactly in the map state and then let's use the modules prop to load the ones we need:

Nice! Now we have controls on the map and we also avoided downloading the full package of Yandex.Maps API.

All components in this library support modules prop, that will allow you to download additional modules when they are needed.

Let's add another one to the example above. This time we will add balloon to the placemark. Balloon module is not downloaded with the base minimum bundle of Yandex.Maps API, so to actually see ballon we need to specify balloon addon as a module on the Placemark component.

Loading Modules With YMaps Provider query Prop

Manually specifying required modules is not the only way to load them. You can also take advantage of load option when you are specifying query on your Provider component.

This option is part of Yandex.Maps API request and can be used to define what modules you want to load right away with the Yandex.Maps API.

Lets see how the previous example could be changed to use this option:

Notice how we removed all modules props from all components and used query.load prop instead to specify all modules that are required.

Yandex.Maps API default value for this option is package.full. Setting query.load to 'package.full' will set this library to the mode that is completely matching the default Yandex.Maps API behavior

You can learn more about Yandex.Maps API on-demand module system and API loading parameters in Yandex.Maps documentation.

Controlled and Uncontrolled Components

Important React pattern that you should be aware of when using this library is controlled and uncontrolled components. This pattern is all about who is responsible for handling updates and storing components state.

Applied to this library, that means that based on which props you are using, either Yandex.Maps API or your application will be responsible for being the source of truth for your map objects.

In the example below, map state (more specifically zoom and coordinates) is controlled by application on the first map component, but is not controlled by application on the second map component. When you click the button, first map zoom and coordinates will be updated, but the second map will preserve its state. This happens because instead of state prop, we are using defaultState prop.

import React from 'react';

export default function App() {
const [zoom, setZoom] = React.useState(9);
const mapState = React.useMemo(
() => ({ center: [55.75, 37.57], zoom }),
[zoom]
);

return (
<YMaps>
<>
<table>
<tbody>
<tr>
<th>Controlled Map</th>
<th>Uncontrolled Map</th>
</tr>
<tr>
<td>
<Map state={mapState} />
</td>
<td>
<Map defaultState={mapState} />
</td>
</tr>
</tbody>
</table>
<p>
<button onClick={() => setZoom((zoom) => (zoom === 9 ? 12 : 9))}>
Toggle map zoom
</button>
</p>
</>
</YMaps>
);
}

Every prop on every map object is this library supports the default version (e.g, state and defaultState, options and defaultOptions, properties and defaultProperties, geometry and defaultGeometry). By choosing to use default version you are opting out of this library updating map objects when the props are changed.

As mentioned in the "What Is Supported" section, there is no way to prevent Yandex.Maps from updating maps objects state completely, so it is very easy to go out of sync if you are using these components in a controlled way and not synchronizing the state back to your application state.

From the personal experience, you would want to use default props for most of the cases in your application.

If you want to know more about controlled and uncontrolled components, there are a few useful links from React documentation:

React Context. Provider and Consumer Components

This library uses React Context API to provide Yandex.Maps API to every component, that needs it.

This library also uses React Context API so parent Yandex.Maps objects (e.g., Map, Clusterer, ObjectManager) could provide children Yandex.Maps objects with a parent instance.

If you want to know more about React Context and Provider/Consumer components, you can check out React documentation section on the topic.

Make sure that you used YMaps provider component and all Yandex.Maps objects are inside this component tree. This library will throw an error, if the Yandex.Maps context is missing.