使用google-maps-react时如何避免显示InfoWindow时整个地图重渲染?
问题根因
父组件MyMap调用setState修改visible状态时,会触发整个父组件的render方法全量执行,<Map>容器和所有<Marker>子组件都会重新执行渲染逻辑,上百个标记同时重绘就会出现肉眼可见的闪烁。
解决方案
- 方案1:拆分组件隔离状态范围
把InfoWindow相关的状态和逻辑从父组件中抽离,单独封装为子组件,修改visible状态的逻辑也放在这个子组件内部,状态变更只会触发该子组件重渲染,不会影响父级的Map和Marker组件。
如果不想拆分组件的话,将所有Marker组件改为继承React.PureComponent(类组件场景),或者用React.memo包裹(函数组件场景),组件会自动对props做浅比较,props没有变化的Marker不会触发重渲染:
// 封装纯组件示例 class MyMarker extends React.PureComponent { render() { return <Marker {...this.props} /> } }
注意所有传递给Map、Marker的props都要保持引用稳定,不要在render方法内直接定义匿名回调函数、字面量对象作为props,比如不要写<Map onClick={() => handleClick()}>,所有回调函数都提前在构造函数绑定或者声明为类属性箭头函数,避免每次render生成新的引用导致浅比较失效触发不必要重渲染。
- 方案2:启用Marker原生优化属性
google-maps-react的<Marker>组件原生支持optimized属性,设置为true后会将标记渲染到独立的canvas层,大幅降低重绘开销:
<Marker optimized={true} position={xxx} onClick={xxx} />
- 方案3:状态独立管理
把InfoWindow的visible状态放到独立的状态容器管理,Map和Marker组件不依赖这个状态,只有InfoWindow组件订阅该状态,状态变更时只会触发InfoWindow本身重渲染。
内容的提问来源于stack exchange,提问作者OwlR
相关产品推荐
相关产品推荐

