Работа с React
Вы можете работать с картой MapGL JS API в проектах на React. Обратите внимание на следующие инструкции:
- Как добавить карту в приложение и избежать повторного рендеринга карты.
- Как получить доступ к карте из другого компонента.
Примечание
Вы можете воспользоваться шаблоном React-проекта.
Повторный рендеринг
Возьмём для примера простое приложение на React:
import React from 'react';
import ReactDOM from 'react-dom';
import { App } from './App';
const rootElement = document.getElementById('root');
ReactDOM.render(<App />, rootElement);
С простым компонентом App:
import React from 'react';
export const App = () => {
return <div>My App</div>;
};
Чтобы добавить в это приложение карту, создадим новый компонент:
import { load } from '@2gis/mapgl';
export const Map = () => {
useEffect(() => {
let map;
load().then((mapglAPI) => {
map = new mapglAPI.Map('map-container', {
center: [55.31878, 25.23584],
zoom: 13,
key: 'Your API access key',
});
});
// Удаляем карту при размонтировании компонента
return () => map && map.destroy();
}, []);
return (
<div style={{ width: '100%', height: '100%' }}>
<MapWrapper />
</div>
);
};
Обратите внимание, что в этом компоненте нет контейнера карты (map-container
). Чтобы избежать повторного рендеринга карты, мы создадим отдельный компонент, который будет использовать React.memo:
const MapWrapper = React.memo(
() => {
return <div id="map-container" style={{ width: '100%', height: '100%' }}></div>;
},
() => true,
);
Второй аргумент React.memo - функция, которая определяет, можно ли использовать последний результат рендеринга, избегая таким образом повторного рендеринга. В нашем случае эта функция будет всегда возвращать true
.
Осталось добавить карту в компонент App и всё готово к работе:
export const App = () => {
return (
<div style={{ width: '100%', height: 400 }}>
<Map />
</div>
);
};
Полный исходный код можно найти в примере ниже.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>2GIS Map API</title>
<meta name="description" content="Example of mapgl initialization in React application" />
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://mapgl.2gis.com/api/js/v1"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
html,
body,
#root {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
</head>
<body>
<div id="root" style="height: 100%;"></div>
<script type="text/babel">
const MapWrapper = React.memo(
() => {
return <div id="map-container" style={{ width: '100%', height: '100%' }}></div>;
},
() => true,
);
const MapGL = () => {
React.useEffect(() => {
const map = new mapgl.Map('map-container', {
center: [55.31878, 25.23584],
zoom: 13,
key: 'Your API access key',
});
// Destroy the map, if Map component is going to be unmounted
return () => map.destroy();
}, []);
return (
<div style={{ width: '100%', height: '100%' }}>
<MapWrapper />
</div>
);
};
const App = () => {
return (
<div style={{ width: '100%', height: '100%' }}>
<MapGL />
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
</script>
</body>
</html>
Получение доступа к карте
Второй частый сценарий использования - получение доступа к карте из другого компонента.
В качестве примера можно взять кнопку, которая меняет центр карты. Если эта кнопка будет расположена в отдельном компоненте, то нужно из этого компонента получить доступ к компоненту с картой. Для этого можно использовать React Context API.
Для начала создадим новый компонент и вызовем React.createContext(), чтобы создать объект Context.
const MapContext = React.createContext([undefined, () => {}]);
const MapProvider = (props) => {
const [mapInstance, setMapInstance] = React.useState();
return (
<MapContext.Provider value={[mapInstance, setMapInstance]}>
{props.children}
</MapContext.Provider>
);
};
Затем обернём компонент App компонентом MapProvider. Это позволит использовать созданный объект Context в компоненте App и всех дочерних компонентах.
ReactDOM.render(
<MapProvider>
<App />
</MapProvider>,
rootElement,
);
Теперь после создания карты мы можем использовать Context, чтобы сохранить ссылку на карту:
export const Map = () => {
const [_, setMapInstance] = React.useContext(MapContext);
useEffect(() => {
let map;
load().then((mapglAPI) => {
map = new mapglAPI.Map('map-container', {
center: [55.31878, 25.23584],
zoom: 13,
key: 'Your API access key',
});
// Сохраняем ссылку на карту
setMapInstance(map);
});
// Удаляем карту при размонтировании компонента
return () => map && map.destroy();
}, []);
return (
<div style={{ width: '100%', height: '100%' }}>
<MapWrapper />
</div>
);
};
Сохранённую ссылку можно использовать в других компонентах приложения. Например, создадим кнопку, которая будет менять центр карты:
export const MoveMapButton = () => {
const [mapInstance] = React.useContext(MapContext);
const setInitialCenter = useCallback(() => {
if (mapInstance) {
mapInstance.setCenter([55.31878, 25.23584]);
}
}, [mapInstance]);
return <button onClick={setInitialCenter}>Set initial center</button>;
};
Полный исходный код можно найти в примере ниже.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>2GIS Map API</title>
<meta
name="description"
content="Example of interactions with a map in React application"
/>
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://mapgl.2gis.com/api/js/v1"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
html,
body,
#root {
margin: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const MapContext = React.createContext([undefined, () => {}]);
const MapProvider = (props) => {
const [mapInstance, setMapInstance] = React.useState();
return (
<MapContext.Provider value={[mapInstance, setMapInstance]}>
{props.children}
</MapContext.Provider>
);
};
const MapWrapper = React.memo(
() => {
return <div id="map-container" style={{ width: '100%', height: '100%' }}></div>;
},
() => true,
);
const MapGL = () => {
const [_, setMapInstance] = React.useContext(MapContext);
React.useEffect(() => {
const map = new mapgl.Map('map-container', {
center: [55.31878, 25.23584],
zoom: 13,
key: 'Your API access key',
});
setMapInstance(map);
// Destroy the map, if Map component is going to be unmounted
return () => map.destroy();
}, []);
return (
<div style={{ width: '100%', height: '100%' }}>
<MapWrapper />
</div>
);
};
const MoveMapButton = () => {
const [mapInstance] = React.useContext(MapContext);
const setInitialCenter = React.useCallback(() => {
if (mapInstance) {
mapInstance.setCenter([55.31878, 25.23584]);
}
}, [mapInstance]);
return (
<button style={{ padding: '4px 10px' }} onClick={setInitialCenter}>
Set initial center
</button>
);
};
const App = () => {
return (
<div>
<div style={{ padding: '0 0 6px' }}>
Drag the map and then click the button <MoveMapButton />
</div>
<br />
<div style={{ width: '100%', height: 250 }}>
<MapGL />
</div>
</div>
);
};
ReactDOM.render(
<MapProvider>
<App />
</MapProvider>,
document.getElementById('root'),
);
</script>
</body>
</html>
Готовый пакет npm
Если вы используете npm, вы можете скачать пакет @2gis/mapgl, который также включает поддержку TypeScript.
Примеры использования и другую информацию можно найти в Readme.
Пример использования в стороннем проекте
Пример использования MapGL в стороннем проекте можно посмотреть в репозитории github.com/city-mobil/frontend_react-2gis, где реализована React-обертка. Также доступен npm пакет этой обертки - react-2gis.