如何利用 Set 实现 React 状态管理中对批量更新列表的去重缓存

作者:袖梨 2026-06-04
React中用Set管理批量更新列表缓存的核心是利用其去重特性与不可变更新模式,通过ref暂存、防抖提交、key归一化及useReducer封装实现高效同步。

在 React 中用 Set 管理批量更新的列表缓存,核心是利用其天然去重特性 + 不可变更新模式,避免重复渲染和冗余数据。关键不在“存”,而在“怎么安全地合并、更新、同步到状态”。

用 Set 做中间缓存层,不直接 setState

不要每次拿到新项就立刻 setState,而是先累积到一个临时 Set,等批量操作完成(比如 API 响应返回、用户连续点击结束)再一次性同步到 React state:

  • 声明一个 ref 持有临时 Set:const pendingItems = useRef(new Set())
  • 添加时只操作 Set:pendingItems.current.add(item)(自动去重)
  • 触发提交时转为数组并更新 state:setList(Array.from(pendingItems.current))
  • 提交后清空:pendingItems.current.clear()

处理对象类列表项:要传入唯一 key,别直接塞对象

Set 对对象按引用判重,两个结构相同但不同引用的对象会被视为不同项。所以实际使用中必须提取唯一标识(如 id)来归一化:

  • 缓存时存 id:pendingItems.current.add(item.id)
  • 同步 state 时查表还原:setList([...pendingItems.current].map(id => itemMap[id])),其中 itemMap 是 id → 完整对象的 Map 缓存
  • 或统一用 JSON.stringify(item) 当 key(仅限简单扁平对象,且注意顺序和 undefined 处理)

配合 useEffect 实现“防抖式”批量提交

当更新来自高频事件(如搜索输入、滚动加载),可用 useEffect + 定时器聚合多次变更:

  • 每次新增都重置定时器:clearTimeout(timerRef.current); timerRef.current = setTimeout(submit, 300)
  • 定时器到时执行一次 Array.from(Set) 同步,确保 300ms 内所有变更只触发一次 re-render
  • 组件卸载前清理定时器,避免内存泄漏

与 useReducer 配合更清晰(推荐中大型场景)

把 Set 缓存逻辑封装进 reducer,让状态更新可追溯、易测试:

  • state 结构含 items: Setlist: [](用于渲染)
  • 定义 ADD_ITEMS action:payload 是数组,reducer 用 new Set([...state.items, ...payload.map(x => x.id)]) 合并
  • 定义 COMMIT action:将 state.items 转成 list 并覆盖 state.list,再清空 items Set
  • 组件内 dispatch 多次 ADD_ITEMS,最后 dispatch COMMIT —— 语义明确,调试友好

不复杂但容易忽略:Set 本身不是响应式,它只是工具;真正驱动 UI 更新的仍是最终赋给 state 的那个数组。把 Set 当“草稿本”,把数组当“快照”,边界清晰,就不容易出错。

相关文章

精彩推荐