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

React对象数组过滤:为何第一种实现失效?求最优方案

数组过滤失效原因及最优实现方案

一、两种实现的差异原因

第一种实现失效的核心问题

  1. 异步状态更新延迟:setInputValue是React异步状态更新方法,执行filter时,inputValue还是更新前的旧值,导致过滤逻辑用错了输入内容。
  2. 原始数据被覆盖:直接用setData(filteredNotes)把过滤后的子集替换了原始完整数据。第一次过滤后,data就变成了原始数据的一部分,后续再输入过滤条件时,只能基于这个子集继续筛选,最终导致原始数据丢失,看起来像是“误删”。

第二种实现正常的原因

始终保留原始完整数据在data状态里,没有修改它。每次组件渲染时,都基于最新的inputValue对原始数据做实时过滤,既保证了过滤逻辑用的是最新输入值,又不会丢失原始数据。

二、最优实现方式

根据数据规模和业务需求,有几种不同的最优方案:

1. 小数据量场景(直接用渲染时过滤)

就是第二种实现的思路,代码简洁易维护,不需要额外优化:

const [data, setData] = useState(JSON.parse(localStorage.getItem("notes") ?? "[]"));
const [inputValue, setInputValue] = useState("");

return (
  <>
    <input onChange={(e) => setInputValue(e.target.value)} value={inputValue}/>
    {data
      .filter((val) => val.text.toLowerCase().includes(inputValue.toLowerCase()))
      .map((note) => (
        <Note
          key={note.id}
          note={note}
          onExpandCheck={setIsExpandedCheck}
          onNoteDelete={handleNoteDelete}
          onNoteSave={handleNoteSave}
        />
      ))}
  </>
)

(注:这里把inputValue也转成小写,避免大小写敏感的问题)

2. 大数据量场景(用useMemo缓存过滤结果)

如果数据量很大,每次渲染都执行filter会有性能损耗,可以用useMemo缓存过滤后的结果,只有当data或inputValue变化时才重新计算:

const [data, setData] = useState(JSON.parse(localStorage.getItem("notes") ?? "[]"));
const [inputValue, setInputValue] = useState("");

// 缓存过滤结果
const filteredData = useMemo(() => {
  return data.filter(val => val.text.toLowerCase().includes(inputValue.toLowerCase()))
}, [data, inputValue])

return (
  <>
    <input onChange={(e) => setInputValue(e.target.value)} value={inputValue}/>
    {filteredData.map((note) => (
      <Note
        key={note.id}
        note={note}
        onExpandCheck={setIsExpandedCheck}
        onNoteDelete={handleNoteDelete}
        onNoteSave={handleNoteSave}
      />
    ))}
  </>
)

3. 需要保留过滤后状态的场景

如果业务需要同时保留原始数据和过滤后的状态(比如需要对过滤结果做修改),可以把原始数据存在单独的状态或useRef里:

// 保存原始完整数据
const [rawData, setRawData] = useState(JSON.parse(localStorage.getItem("notes") ?? "[]"));
const [inputValue, setInputValue] = useState("");
// 可选:如果需要单独维护过滤后的状态
const [filteredData, setFilteredData] = useState(rawData);

// 监听输入变化,更新过滤结果
useEffect(() => {
  setFilteredData(rawData.filter(val => val.text.toLowerCase().includes(inputValue.toLowerCase())))
}, [rawData, inputValue])

return (
  <>
    <input onChange={(e) => setInputValue(e.target.value)} value={inputValue}/>
    {filteredData.map((note) => (
      <Note
        key={note.id}
        note={note}
        onExpandCheck={setIsExpandedCheck}
        onNoteDelete={handleNoteDelete}
        onNoteSave={handleNoteSave}
      />
    ))}
  </>
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 23:10:11