You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:32:22