React state中存储的数组更新异常,下拉筛选数组未按预期更新是什么原因?
问题根因
- React的状态更新是异步的,在
onChange回调中执行setlocation后立刻调用filterLocations,此时函数内部读取的location还是更新前的旧值,拿不到最新的输入内容。 - 筛选逻辑存在漏洞:遍历
allLocations的过程中,只要遇到一个不匹配的元素就直接清空dropDownLocations,会把之前已经匹配到的结果全部清除;同时循环内多次调用setdropDownLocations,由于状态更新的批量合并特性,每次读取的dropDownLocations都是遍历开始前的旧值,无法正确累加匹配结果。 - 没有在每次筛选前清理上一次的匹配结果,会导致多次输入的结果混乱叠加。
修正后代码
import "./App.css"; import { useState, useEffect } from "react"; function App() { // 用户输入的位置 const [location, setLocation] = useState(""); const [allLocations, setAllLocations] = useState(["F-1", "F-2", "G-1", "G-2"]); const [dropDownLocations, setDropDownLocations] = useState([]); // 监听location变化,自动触发筛选 useEffect(() => { // 直接用filter方法一次性筛选所有符合条件的元素 const matchedLocations = allLocations.filter(item => item.includes(location)); setDropDownLocations(matchedLocations); }, [location, allLocations]); return ( <div className="App"> <div> <input value={location} onChange={(e) => setLocation(e.target.value)} /> <ul> {dropDownLocations.map((i) => ( <li key={i}>{i}</li> ))} </ul> </div> </div> ); } export default App;
修正说明
- 用
useEffect监听location的变化,每次输入更新location完成后再执行筛选逻辑,保证拿到的是最新的输入值 - 直接通过
Array.filter方法一次性得到所有匹配的结果,统一调用setDropDownLocations更新状态,避免了循环内多次更新状态的问题 - 每次筛选都会生成全新的匹配结果数组,直接覆盖旧的下拉选项数组,不需要手动清空,也不会出现结果叠加的问题
内容的提问来源于stack exchange,提问作者Sami Malik
相关产品推荐
相关产品推荐

