首页 > 解决方案 > React 服务单例替代方案

问题描述

我正在使用谷歌地图库制作一个 ReactJS 应用程序,并且我正在尝试将大多数地图逻辑抽象为服务,以便将来如果我想的话,我可以将谷歌地图库与传单交换。

它现在的工作方式是我有一个组件加载地图库并将其附加到 div。回调将onLoad在此服务中设置地图,以便我可以保留对它的引用。

onMapLoad={(map: Map) => {
    mapService.setMap(map);
    props.mapLoaded();
}}

该服务还需要访问我的 redux 存储以在例如选择地图上的某个标记时调度操作。我在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
}

标签: reactjsdesign-patternsreduxsingleton

解决方案


推荐阅读