React google maps 标记在组件重新渲染后消失

React google maps Markers disappear after component re-render

我在使用 react-google-maps 模块时遇到问题,即标记和组件重新渲染。

场景是这样的:

  1. 加载带有地图和 2-3 个标记的页面(确定)
  2. 单击导航栏上的选项卡 -> 页面以单页应用程序方式呈现其他内容(确定)
  3. 单击导航栏上返回地图的选项卡 -> 页面呈现地图但未呈现标记。

我在州内保存标记数据,并将它们应用到 onGoogleApiLoaded={({map, maps}) => this.renderMarkers(map, maps)} 中的地图。

我设法通过将 renderMarkers 包装在一秒的 setTimeout 中解决了这个问题,并且它以这种方式加载正常。

我不喜欢这个解决方案,我相信我只是没有按照我应该的方式去做。我相信标记会尝试将自己放置在未呈现的地图上,但奇怪的是即使没有 setTimeout 它也适用于默认页面(可能与反应组件生命周期有关,我不知道)。

有没有办法在地图完全加载后附加 属性 onGoogleApiLoaded={({map, maps}) => this.renderMarkers(map, maps)}?或者至少延迟它,直到我 100% 确定地图已加载,而不是随机数秒。

编辑:我用 marker.setMap(map) 方法分配标记,我只是尝试在标记的构造函数中设置 属性 map: map 但行为保持不变。

当您说您单击一个选项卡并且页面呈现其他内容时,您可能正在卸载地图组件。如果您将标记保存在您所说的状态中,您可以在 componentWillUnmount.

中自行检查
componentWillUnmount() {
  console.log('Unmount');
}

如果该控制台日志显示在您的控制台中,则意味着您正在卸载组件并丢失您所在状态下的标记数据。

现在,为了使用您的标记加载地图,您可以使用 componentDidMount. I'm not sure how react-google-maps differs from react-leaflet (the map component I have experience with) but I'm guessing the map has a property where you pass it the markers you're keeping in the state. Instead of a timeout you should probably use componentWillMount or componentDidUnmount 反应生命周期方法等待地图完全加载以获取您的标记数据。

componentDidMount() { // It should work with componentWillMount too
  this.fetchMarkersData();
}

fetchMarkersData() {
  // ... get your data
  this.setState({ markers: markersData });
}

render() {
  return (
    <MapComponent
      markers={this.state.markers}
    />
  );
}

在我进一步分解问题后,我明白了这一点。问题是由于我丢失了保存在地图组件状态中的标记数据(它是具有导航栏的组件的子组件)。

所以流程是这样的:

  1. 页面的首次呈现 -> 所有内容都加载正常,因为所有内容都是第一次呈现(包括标记)。
  2. 我渲染另一个组件,前一个组件被破坏并失去状态。
  3. 我重新渲染了 Map 组件,但它没有状态,因此它没有供标记使用的数据。

自然地,解决方案是将状态向上移动一个级别到父级并将其作为 Map 组件的道具向下传递,现在一切正常。

奖金:

我想提一下我必须解决的另一件事,但对于其他偶然发现此问题的人来说不一定有用: 我正在使用导航栏来浏览我的页面(使用 react-router-dom)。

将状态上移到父级时,参数不会像这样传递给 <Route 元素:<Route path="/" component={Map} markerData={this.state.markerData}/> 而是使用 render 属性 像这样:<Route exact path="/" render={props => <Map markerData={this.state.markerData}/>} 以便 Map 组件获得 props 而不是 Router.