
当输入框失焦(onblur)与下拉项点击(onclick)同时触发时,react 可能因状态更新顺序导致点击事件被忽略;本文提供可靠方案:移除 onblur 控制、改用显式关闭逻辑,并优化状态命名以提升可维护性。
在构建带自动补全功能的搜索栏时,一个常见陷阱是:用户点击下拉列表中的选项后,输入框内容未更新。其根本原因并非 react 的 bug,而是浏览器事件流与 React 状态更新机制共同作用下的事件竞态(Event race condition)——onBlur 在 onClick 之前被触发,setFocused(false) 导致下拉区域立即卸载,使得 onClick 处理函数虽已注册但实际未执行(dom 节点已被移除)。
✅ 正确解法:避免依赖 onBlur,由点击行为主动控制显示状态
核心原则是:让“关闭下拉”的动作由用户明确触发(如点击选项),而非隐式响应失焦。这既符合直觉,也规避了事件时序不确定性。
以下是优化后的完整实现:
function app() { const [value, setValue] = React.useState(""); const [showSuggestions, setShowSuggestions] = React.useState(false); // 更语义化的状态名 return ( <> setValue(e.target.value)} onFocus={() => setShowSuggestions(true)} // ❌ 移除 onBlur —— 不再靠它控制显示逻辑 /> {showSuggestions && ({ setValue("item 1"); setShowSuggestions(false); // 显式关闭 }} > item 1