react-google-maps中StandaloneSearchBox组件卸载问题求助
我之前也踩过react-google-maps里StandaloneSearchBox卸载报错的坑,大概率是组件卸载时Google Places API的Autocomplete实例没被正确清理,导致内存泄漏或者DOM相关报错。下面是我亲测有效的解决方案:
问题根源
StandaloneSearchBox内部封装了Google Places的Autocomplete实例,但部分版本的库没有自动处理组件卸载时的实例销毁逻辑,导致实例仍持有对已卸载DOM元素的引用,触发报错。
解决方案步骤
核心思路是手动保存Autocomplete实例引用,在组件卸载时调用原生API清理资源:
1. 类组件适配方案(匹配你的代码结构)
import React, { Component } from "react"; import PropTypes from "prop-types"; import { withScriptjs } from "react-google-maps"; import StandaloneSearchBox from "react-google-maps/lib/components/places/StandaloneSearchBox"; import { Input } from "semantic-ui-react"; import API_KEY from "../config/googleAPI"; class SearchBox extends Component { // 创建ref保存SearchBox实例,用于获取底层Autocomplete对象 searchBoxRef = React.createRef(); // 组件卸载时清理资源 componentWillUnmount() { const searchBoxInstance = this.searchBoxRef.current; if (searchBoxInstance) { const autocomplete = searchBoxInstance.getPlacesAutocomplete(); // 解绑Autocomplete所有事件监听 autocomplete?.unbindAll(); // 清除输入框的Google Maps事件监听 google.maps.event.clearInstanceListeners(searchBoxInstance.getInputElement()); } } // 处理地点选择逻辑(按需修改) handlePlacesChanged = () => { const selectedPlaces = this.searchBoxRef.current?.getPlaces(); console.log("选中地点:", selectedPlaces); // 这里可以添加你的业务逻辑,比如更新状态、回传父组件等 }; render() { return ( <StandaloneSearchBox ref={this.searchBoxRef} onPlacesChanged={this.handlePlacesChanged} > <Input placeholder="搜索地点..." fluid /> </StandaloneSearchBox> ); } } // 注意:使用组件时必须传入包含places库的Google Maps脚本地址 export default withScriptjs(SearchBox);
2. 组件使用时的注意事项
确保你在调用组件时,传入的googleMapURL包含places库参数:
// 示例:在父组件中使用SearchBox <SearchBox googleMapURL={`https://maps.googleapis.com/maps/api/js?key=${API_KEY}&libraries=places`} loadingElement={<div style={{ height: "40px" }}>加载中...</div>} />
3. 函数组件版本(如果后续重构可用)
如果是函数组件,用useEffect的清理函数实现同样逻辑:
import React, { useRef, useEffect } from "react"; import { withScriptjs } from "react-google-maps"; import StandaloneSearchBox from "react-google-maps/lib/components/places/StandaloneSearchBox"; import { Input } from "semantic-ui-react"; import API_KEY from "../config/googleAPI"; const SearchBox = () => { const searchBoxRef = useRef(null); useEffect(() => { // 组件卸载时执行清理 return () => { const searchBoxInstance = searchBoxRef.current; if (searchBoxInstance) { const autocomplete = searchBoxInstance.getPlacesAutocomplete(); autocomplete?.unbindAll(); google.maps.event.clearInstanceListeners(searchBoxInstance.getInputElement()); } }; }, []); const handlePlacesChanged = () => { const selectedPlaces = searchBoxRef.current?.getPlaces(); console.log("选中地点:", selectedPlaces); }; return ( <StandaloneSearchBox ref={searchBoxRef} onPlacesChanged={handlePlacesChanged} > <Input placeholder="搜索地点..." fluid /> </StandaloneSearchBox> ); }; export default withScriptjs(SearchBox);
为什么这能解决问题?
通过getPlacesAutocomplete()获取到Google原生的Autocomplete实例后,调用unbindAll()解绑所有事件,再用clearInstanceListeners()清除输入框上的Google Maps事件监听,彻底切断实例与已卸载DOM的关联,避免内存泄漏和卸载时的报错。
内容的提问来源于stack exchange,提问作者Giannis Tsimarakis
相关产品推荐
相关产品推荐

