如何在不触发重新呈现反应组件的情况下更新谷歌地图?

时间:2016-06-15 16:56:21

标签: javascript google-maps reactjs typescript

我正在尝试抽象在React中创建和渲染谷歌地图的过程 - 到目前为止我已经大部分成功,但我遇到了一个问题。由于我设置的方式,当我更新地图的内容(引脚)时会有一个闪光。 有没有办法更新属性(并将其传递给组件的子级)而不强制重新渲染?

请注意,我正在寻找一种能够传递我正在创建标记作为道具的方法 - 这是否意味着我总是需要重新渲染?

存储-map.tsx

import * as React from 'react';
import { MapComponent, Markable } from '../google';
import { Store } from './store.model';

export interface StoresMapProps {
    stores: Store[];
}

function mapStoreToMarker(store: Store): Markable {
    return {
        title: store.id,
        position: store.geoLoc
    };
}

export class StoresMapComponent extends React.Component<StoresMapProps, void> {
    shouldComponentUpdate(nextProps: StoresMapProps): boolean {
        return nextProps.stores !== this.props.stores;
    }

    render(): JSX.Element {
        const markers = this.props.stores.map(mapStoreToMarker);
        return (<MapComponent center={{ lat: 39.709396, lng: -105.145465 }} zoom={8} markers={markers} />);
    }
}

map.tsx

import * as React from 'react';
import configuration from '../../configuration';
import { GoogleSDK } from './sdk';

export interface Markable {
    position: { lat: number; lon: number; };
    title: string;
}

export interface MapComponentProps extends google.maps.MapOptions {
    markers?: Markable[];
}

export class MapComponent extends React.Component<MapComponentProps, void> {
    private _map: google.maps.Map;
    private _loadTheMap(id: string): void {
        GoogleSDK.load()
            .then(() => this._reallyLoadTheMap(id))
            .then(() => this._reallySetMarkers(this.props.markers));
    }

    private _setMarkers(markers: Markable[]): void {
        GoogleSDK.load().then(() => this._reallySetMarkers(markers));
    }

    private _reallyLoadTheMap(id: string): void {
        const options = Object.assign({}, this.props, {
            mapTypeId: this.props.mapTypeId || google.maps.MapTypeId.ROADMAP,
            center: this.props.center || configuration.google.maps.defaults.center,
            zoom: this.props.zoom || configuration.google.maps.defaults.zoom,
            mapTypeControl: this.props.mapTypeControl || false
        });

        this._map = new google.maps.Map(document.getElementById(id), options);
    }

    private _reallySetMarkers(markers: Markable[]): void {
        markers.forEach(marker => new google.maps.Marker({
            map: this._map,
            title: marker.title,
            position: new google.maps.LatLng(marker.position.lat, marker.position.lon)
        }));
    }

    render(): JSX.Element {
        const id = `MapComponent${new Date().getMilliseconds()}`;
        const style = {
            width: '100%',
            height: '200px',
            lineHeight: '200px',
            textAlign: 'center',
            color: 'white'
        };
        this._loadTheMap(id);
        return (<div id={id} style={style}></div>);
    }
}

0 个答案:

没有答案