React SearchBar组件点击建议列表项onClick无响应问题求助
React搜索栏点击建议项无响应的解决方案
问题根源
输入框的onBlur事件会在点击建议列表时立即触发,将showSuggestion设为false,导致建议列表组件被快速卸载,点击事件还没来得及执行就失效了。另外原代码中建议列表的mt-72类会导致定位异常,进一步影响点击区域的可用性。
修复方案
- 给
onBlur的隐藏逻辑添加延迟,让点击事件有足够时间触发 - 调整建议列表的定位样式,确保它出现在输入框下方且处于可点击区域
- 修正状态变量的拼写错误(提升代码可读性)
修正后的完整代码
const SearchBar = () => { const [searchQuery, setSearchQuery] = useState(""); const [showSuggestion, setShowSuggestion] = useState(false); // 修正拼写:searchSuggetions → searchSuggestions const [searchSuggestions, setSearchSuggestions] = useState([]); let blurTimer; useEffect(() => { console.log("api called"); const timer = setTimeout(() => fetchSearchSuggestions(), 200); return () => { clearTimeout(timer); }; }, [searchQuery]); const fetchSearchSuggestions = async () => { const response = await fetch( `http://suggestqueries.google.com/complete/search?client=firefox&ds=yt&q=${searchQuery}` ); const json = await response.json(); setSearchSuggestions(json[1]); }; const handleSuggestionClick = (result) => { setSearchQuery(result); setShowSuggestion(false); // 清除blur的延迟定时器,避免重复执行 clearTimeout(blurTimer); }; const handleSearch = () => { console.log("called handle search"); }; return ( <> {/* 父容器设为relative,让子元素absolute基于它定位 */} <div className="m-2 border-2 rounded-full border-violet-500 w-60 h-8 text-violet-500 items-center inline-flex relative z-10"> <input value={searchQuery} onChange={(e) => setSearchQuery(e.target.value.toLocaleLowerCase())} onFocus={() => { setShowSuggestion(true); // 清除之前的blur定时器 clearTimeout(blurTimer); }} onBlur={() => { // 延迟300ms隐藏建议列表,给点击事件留执行时间 blurTimer = setTimeout(() => setShowSuggestion(false), 300); }} type="text" placeholder="Find news" className="ml-3 focus:outline-none focus:ring-violet-300 bg-gray-900 w-full" /> <button className="hover:text-violet-700" onClick={handleSearch}> <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="w-6 h-6"> <path strokeLinecap="round" strokeLinejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z" /> </svg> </button> {showSuggestion && searchSuggestions.length > 0 && ( {/* 调整定位为top-full,紧贴输入框下方,移除错误的mt-72 */} <div className="top-full left-0 mt-1 w-full absolute rounded-xl bg-slate-50 z-20 shadow-lg"> <ul> {searchSuggestions.map((result, index) => ( <li key={index} className="bg-slate-50 border-b hover:bg-slate-200 px-3 py-2 flex items-center cursor-pointer" onClick={() => handleSuggestionClick(result)} > <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor" className="w-5 h-5 mr-2" > <path strokeLinecap="round" strokeLinejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z" /> </svg> <span>{result}</span> </li> ))} </ul> </div> )} </div> </> ); };
关键修改说明
- 延迟隐藏逻辑:通过
setTimeout给onBlur添加300ms延迟,确保点击事件优先执行;同时在点击建议项时清除该定时器,避免不必要的隐藏操作。 - 定位优化:将父容器设为
relative,建议列表用top-full定位在输入框正下方,移除原代码中错误的mt-72类,保证列表在可视区域内且可被点击。 - 结构优化:将
<ul>标签提到循环外部,避免创建多个无意义的列表容器,提升代码结构合理性。 - 拼写修正:统一状态变量名为
searchSuggestions,减少代码混淆。
内容的提问来源于stack exchange,提问作者Mayuresh
相关产品推荐
相关产品推荐

