React google maps 标记在组件重新渲染后消失
React google maps Markers disappear after component re-render
我在使用 react-google-maps 模块时遇到问题,即标记和组件重新渲染。
场景是这样的:
- 加载带有地图和 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}
/>
);
}
在我进一步分解问题后,我明白了这一点。问题是由于我丢失了保存在地图组件状态中的标记数据(它是具有导航栏的组件的子组件)。
所以流程是这样的:
- 页面的首次呈现 -> 所有内容都加载正常,因为所有内容都是第一次呈现(包括标记)。
- 我渲染另一个组件,前一个组件被破坏并失去状态。
- 我重新渲染了 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
.
我在使用 react-google-maps 模块时遇到问题,即标记和组件重新渲染。
场景是这样的:
- 加载带有地图和 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}
/>
);
}
在我进一步分解问题后,我明白了这一点。问题是由于我丢失了保存在地图组件状态中的标记数据(它是具有导航栏的组件的子组件)。
所以流程是这样的:
- 页面的首次呈现 -> 所有内容都加载正常,因为所有内容都是第一次呈现(包括标记)。
- 我渲染另一个组件,前一个组件被破坏并失去状态。
- 我重新渲染了 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
.