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

Shadcn Accordion内Google Maps Autocomplete无法给出地点建议的解决方法

解决Google Places Autocomplete在Shadcn Accordion内无地点建议的问题

问题根源

Shadcn的AccordionContent在折叠状态下会将内部元素设为display: none,而Google Places Autocomplete初始化时依赖输入框的可见状态。组件挂载时Accordion默认折叠,输入框不可见,导致Autocomplete无法完成完整的初始化绑定,自然无法触发地点建议。而开发模式热更新时Accordion已展开,输入框处于可见状态,所以初始化能正常生效。

解决方案

方法1:监听Accordion展开状态动态初始化

通过跟踪Accordion的展开状态,在展开后初始化Autocomplete,折叠时销毁旧实例避免内存泄漏:

import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "../components/ui/accordion"
import { Input } from "../components/ui/input";
import { useEffect, useRef, useState } from "react";

export default function AccountSettings() {
  const autoCompleteRef = useRef<HTMLInputElement>(null);
  const autoCompleteInstanceRef = useRef<google.maps.places.Autocomplete | null>(null);
  const [isOpen, setIsOpen] = useState(false);

  useEffect(() => {
    // 折叠时清理旧实例
    if (!isOpen && autoCompleteInstanceRef.current) {
      google.maps.event.clearInstanceListeners(autoCompleteInstanceRef.current);
      autoCompleteInstanceRef.current = null;
      return;
    }

    // 展开时初始化新实例
    if (isOpen && autoCompleteRef.current && !autoCompleteInstanceRef.current) {
      autoCompleteInstanceRef.current = new google.maps.places.Autocomplete(autoCompleteRef.current);
    }
  }, [isOpen]);

  return (
    <div>
      <Accordion 
        type="single" 
        collapsible 
        onValueChange={(value) => setIsOpen(value === "item-1")}
      >
        <AccordionItem value="item-1">
          <AccordionTrigger>
            <span>Location Accordion</span>
          </AccordionTrigger>
          <AccordionContent>
            <Input ref={autoCompleteRef} placeholder="Choose a location" />
          </AccordionContent>
        </AccordionItem>
      </Accordion>
    </div>
  )
}

方法2:用IntersectionObserver监听输入框可见性

如果不想依赖Accordion的状态,可以通过IntersectionObserver监听输入框是否进入可视区域,在可见时初始化:

import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "../components/ui/accordion"
import { Input } from "../components/ui/input";
import { useEffect, useRef } from "react";

export default function AccountSettings() {
  const autoCompleteRef = useRef<HTMLInputElement>(null);
  const autoCompleteInstanceRef = useRef<google.maps.places.Autocomplete | null>(null);

  useEffect(() => {
    if (!autoCompleteRef.current) return;

    const observer = new IntersectionObserver((entries) => {
      const [entry] = entries;
      if (entry.isIntersecting && !autoCompleteInstanceRef.current) {
        // 元素可见时初始化Autocomplete
        autoCompleteInstanceRef.current = new google.maps.places.Autocomplete(autoCompleteRef.current!);
      } else if (!entry.isIntersecting && autoCompleteInstanceRef.current) {
        // 元素不可见时销毁实例
        google.maps.event.clearInstanceListeners(autoCompleteInstanceRef.current);
        autoCompleteInstanceRef.current = null;
      }
    }, { threshold: 0.1 });

    observer.observe(autoCompleteRef.current);

    return () => {
      observer.disconnect();
      if (autoCompleteInstanceRef.current) {
        google.maps.event.clearInstanceListeners(autoCompleteInstanceRef.current);
      }
    };
  }, []);

  return (
    <div>
      <Accordion type="single" collapsible>
        <AccordionItem value="item-1">
          <AccordionTrigger>
            <span>Location Accordion</span>
          </AccordionTrigger>
          <AccordionContent>
            <Input ref={autoCompleteRef} placeholder="Choose a location" />
          </AccordionContent>
        </AccordionItem>
      </Accordion>
    </div>
  )
}

关键注意事项

  • 必须清理旧实例:每次折叠或组件卸载时,调用google.maps.event.clearInstanceListeners销毁Autocomplete实例,避免内存泄漏和事件冲突。
  • 避免在组件挂载时直接初始化:此时输入框处于不可见状态,Google API无法完成完整的事件绑定和建议面板初始化。

内容的提问来源于stack exchange,提问作者Jasperan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 16:43:28