Я создаю приложение ReactJS с использованием библиотеки карт Google и пытаюсь абстрагировать большую часть логики карт в сервисе, чтобы в будущем я мог обменяться библиотекой карт Google с листовкой.
Теперь он работает так, что у меня есть компонент, загружающий библиотеку карт и присоединяющий его к div.Обратный вызов onLoad
установит карту в этом сервисе, чтобы я мог сохранить ссылку на нее.
onMapLoad={(map: Map) => {
mapService.setMap(map);
props.mapLoaded();
}}
Служба также должна иметь доступ к моему магазину притока для отправки действий, когда, например, выбран определенный маркер на карте.Я устанавливаю это при загрузке приложения в index.tsx
файле
const store = getStore();
mapService.setStore(store);
Сам сервис является одноэлементным, но мне интересно, есть ли лучший шаблон для использования с React или вообще.Я выложу более короткую версию сервиса, некоторые методы для краткости опущены.У кого-нибудь есть шаблонный совет, который может улучшить эту практику?
interface MapService {
predictPlaces: (query: string) => Observable<AutocompletePrediction[]>;
setStore: (store: Store<StoreState>) => void;
addMarkerToMap: (place: Place) => void;
centerMapAroundSuggestion: (suggestion: Suggestion) => void;
setMap: (newMap: Map) => void;
}
let predictService: google.maps.places.AutocompleteService;
let geocoder: google.maps.Geocoder;
let map: Map;
let store: Store;
let markers: google.maps.Marker[] = [];
const setMap = (newMap: Map) => {
map = newMap;
}
const setStore = (store: Store) => {
store = Store;
}
const centerMapAroundSuggestion = (suggestion: Suggestion) => {
if (!map) {
throwGoogleMapsNotLoaded();
}
if (!geocoder) {
geocoder = new google.maps.Geocoder();
}
... further implementation ...
}
const predictPlaces = (query: string): Observable<AutocompletePrediction[]> => {
if (!map) {
return of([]);
}
if (!predictService) {
predictService = new google.maps.places.AutocompleteService();
}
... further implementation ...
}
const addMarkerToMap = (place: Place, onSelect: () => void) => {
const marker = createMarker(place, onSelect);
markers.push(marker);
}
const createMarker = (place: Place): Marker => {
if (!map) {
throwGoogleMapsNotLoaded();
}
const marker = new google.maps.Marker({
...options...
});
marker.addListener('click', () => {
createInfoWindow(marker)
if(!!store) {
store.dispatch(createMarkerClicked(place))
}
});
... further implementation ...
}
function throwGoogleMapsNotLoaded() {
throw new Error('Google maps not loaded');
}
export const mapService: MapService = {
predictPlaces,
addMarkerToMap,
setMap,
setStore,
centerMapAroundSuggestion
}