更新标记而无需重新加载整个地图

时间:2019-12-29 16:42:19

标签: reactjs react-google-maps

import React from 'react';
import {GoogleMap, withScriptjs, withGoogleMap, Marker} from 'react-google-maps';
import {db} from './Firebase';
import {useState, useEffect}  from 'react';
import InfoWindow from 'react-google-maps/lib/components/InfoWindow';
import Card from '@material-ui/core/Card';
import CardContent from '@material-ui/core/CardContent';
import AppBar from '@material-ui/core/AppBar';
import Toolbar from '@material-ui/core/Toolbar';
import { CssBaseline } from '@material-ui/core';
import { makeStyles } from '@material-ui/styles';
import IconButton from '@material-ui/core/IconButton'
import KeyboardArrowLeftRounded from '@material-ui/icons/KeyboardArrowLeftOutlined';


const useStyles = makeStyles( theme =>({
  appBar: {
    backgroundColor: '#1976d2'
  },
  card :{
    marginTop: 60
  }
}));

const Maps = (props) =>
  {
    const classes = useStyles();
    const [positions, setPosition] = useState([])
    useEffect(() => {
        const unsub = db.collection('Location').onSnapshot (snapshot => {
          const allPositions = snapshot.docs.map(doc => ({
            id: doc.id,
            ... doc.data()
          }));
          setPosition(allPositions);
        })
        return () => {
          unsub();
        };
      }, [])

    const WrappedMap = withScriptjs(withGoogleMap(props => (
      <GoogleMap defaultZoom = {13}
        defaultCenter = {{ lat: -1.292066 , lng : 36.821945}}>
        {
          positions.map(positioning => (
              props.isMarkerShown &&
                <Marker key = {positioning.id}
                  position = {{lat: positioning.Latitude , lng: positioning.Longitude}}
                ></Marker>
            )
          )
        }

        {
          positions.map(positioning => (
            <InfoWindow key = {positioning.id} defaultPosition = {{lat: positioning.Latitude, lng: positioning.Longitude}}>
              <div>
                {positioning.Team} <br/>
                <a href = "/Nav"> Message </a>
              </div>
            </InfoWindow>
          ))
        }         

      </GoogleMap>)));

    return (
      <div>
        <div>
          <CssBaseline/>
          <AppBar position = "fixed" color = "primary" className = {classes.appBar}>
            <Toolbar>
              <IconButton color = "inherit" edge = "start" onClick={() => props.history.goBack()}>
                <KeyboardArrowLeftRounded/>
              </IconButton>
            </Toolbar>
          </AppBar>
        </div>
        <div>
          <Card className = {classes.card}>
            <CardContent>
              <div style = {{width: "97vw", height: "90vh"}}> 
                <WrappedMap
                  isMarkerShown 
                  googleMapURL={`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=geometry,drawing,places&key=AIzaSyD29SDFXKcqARovEjwUqKl0ysEFKK7GCmU`}
                  loadingElement={<div style={{ height: `100%` }} />}
                  containerElement={<div style={{ height: `100%` }} />}
                  mapElement={<div style={{ height: `100%` }} />}
                  />
              </div>
            </CardContent>
          </Card>
        </div>
      </div>
    )
  };

export default Maps;

我正在使用上面的代码来渲染从Firebase获取的位置的标记和信息窗口。当前,在Firebase中进行更新时,将再次呈现整个mapview,以更新标记和信息窗口的位置。在Firebase中进行更新时,如何只重新渲染标记。

2 个答案:

答案 0 :(得分:0)

您可以通过使用PureComponent防止重新渲染。 在您的情况下,定位是重新渲染“标记”和“信息窗口”。

下面的“更新的代码”将仅重新呈现更新的/新添加的标记。

return third

答案 1 :(得分:0)

在您的示例中,WrappedMap每次都会重新创建。一种解决方案(防止Google Maps API重新加载和地图重新渲染)是将WrappedMap的{​​{1}}组件 的实例化Maps

const WrappedMap = withScriptjs(
  withGoogleMap(props => (
    <GoogleMap
      defaultZoom={5}
      defaultCenter={{ lat: -24.9929159, lng: 115.2297986 }}
    >
      {props.places.map(
        position =>
          props.isMarkerShown && (
            <Marker
              key={position.id}
              position={{
                lat: position.lat,
                lng: position.lng
              }}
            ></Marker>
          )
      )}
    </GoogleMap>
  ))
);

然后通过positions道具来反映地图上的最新位置:

function Map() {     
  return (
    <div>
      <WrappedMap
        isMarkerShown
        positions={positions}
        googleMapURL={`https://maps.googleapis.com/maps/api/js?key=AIzaSyD29SDFXKcqARovEjwUqKl0ysEFKK7GCmU`}
        loadingElement={<div style={{ height: `100%` }} />}
        containerElement={<div style={{ height: `400px` }} />}
        mapElement={<div style={{ height: `100%` }} />}
      />
    </div>
  );
}