Next.js中usePlacesAutocomplete组件二次进入失效问题排查
排查Next.js中usePlacesAutocomplete路由切换后失效的问题
核心原因分析
这种问题通常和Next.js客户端路由特性、Google Places脚本的初始化逻辑直接相关:
- Google Places脚本未重新初始化:Next.js客户端导航(比如用
Link组件跳转)不会刷新整个页面,Google Places脚本可能已加载,但usePlacesAutocomplete内部的初始化钩子在组件重新挂载时未触发,导致ready状态无法更新为true。 - 组件状态残留:路由切换返回时,组件的内部状态(如输入框值、联想列表状态)未重置,导致联想功能的监听逻辑没有重新绑定。
- 依赖项配置错误:如果封装了自定义组件,
usePlacesAutocomplete的依赖项设置不当,会导致组件重新挂载时钩子没有重新执行初始化。
具体解决步骤
1. 绑定脚本加载与组件初始化
若使用@react-google-maps/api库,将LoadScript组件放在使用usePlacesAutocomplete的组件内部,同时确保组件在客户端环境运行(App Router需添加'use client'指令):
'use client'; import { LoadScript } from '@react-google-maps/api'; import usePlacesAutocomplete from '@react-google-maps/api/lib/places/usePlacesAutocomplete'; export default function AddressInput() { const { ready, value, suggestions, setValue, clearSuggestions } = usePlacesAutocomplete({ requestOptions: { componentRestrictions: { country: 'cn' }, // 示例:限制国内地址 }, }); return ( <LoadScript googleMapsApiKey="YOUR_API_KEY" libraries={['places']} > <input value={value} onChange={(e) => setValue(e.target.value)} disabled={!ready} placeholder="输入地址" /> {/* 渲染联想建议列表 */} {suggestions.length > 0 && ( <ul> {suggestions.map((suggestion) => ( <li key={suggestion.place_id} onClick={() => setValue(suggestion.description)}> {suggestion.description} </li> ))} </ul> )} </LoadScript> ); }
这样每次组件挂载时,LoadScript都会检查Google Places脚本的加载状态,确保usePlacesAutocomplete能正确初始化。
2. 监听路由变化重置状态
利用Next.js的路由钩子监听路径变化,当回到当前页面时手动重置autocomplete的状态:
'use client'; import { usePathname } from 'next/navigation'; import { useEffect } from 'react'; import usePlacesAutocomplete from '@react-google-maps/api/lib/places/usePlacesAutocomplete'; export default function AddressInput() { const pathname = usePathname(); const { ready, value, setValue, clearSuggestions, refresh } = usePlacesAutocomplete({ requestOptions: { /* 你的配置 */ }, }); useEffect(() => { // 假设当前页面路径是 /address if (pathname === '/address') { setValue(''); clearSuggestions(); // 调用refresh方法重新初始化autocomplete(部分版本的库支持) refresh?.(); } }, [pathname, setValue, clearSuggestions, refresh]); // 渲染输入框和建议列表... }
3. 清理事件监听避免状态残留
如果手动绑定了输入框的事件监听,务必在组件卸载时移除,防止状态残留:
'use client'; import { useEffect, useRef } from 'react'; import usePlacesAutocomplete from '@react-google-maps/api/lib/places/usePlacesAutocomplete'; export default function AddressInput() { const inputRef = useRef(null); const { setValue } = usePlacesAutocomplete({ /* 配置 */ }); useEffect(() => { const handleInput = (e) => setValue(e.target.value); inputRef.current?.addEventListener('input', handleInput); // 卸载时移除监听 return () => { inputRef.current?.removeEventListener('input', handleInput); }; }, [setValue]); return <input ref={inputRef} />; }
4. 避免全局加载脚本
不要在layout.js(App Router)或_app.js(Pages Router)中全局加载Google Maps脚本,而是在需要的组件内部加载,避免路由切换时的脚本冲突。
内容的提问来源于stack exchange,提问作者Nicolas Castera
相关产品推荐
相关产品推荐

