concat适合无限滚动中安全拼接数据,但需避免高频大数组创建;应校验newItems类型、用虚拟滚动优化性能,并配合去重与错误处理机制。

在无限滚动列表中,用 concat 拼接新数据块是常见做法,但需注意它返回新数组、不修改原数组,且频繁调用可能影响性能。关键不是“能不能用”,而是“怎么用得安全又高效”。
concat 的基本用法和注意事项
concat 是纯函数,不会改变原数组,适合函数式更新场景:
- 它接受任意数量的参数(数组、值、类数组),会扁平化一层,但不会递归展开嵌套数组
- 拼接后返回全新数组,原数组保持不变——这对 React/Vue 等依赖引用变化触发更新的框架很友好
- 如果新数据为空数组或
undefined,concat仍会返回副本,不是原地复用,要注意内存开销
在无限滚动中的典型使用模式
假设你维护一个 items 状态(如 React 的 useState),每次加载成功后追加新数据:
- 正确写法:
setItems(prev => prev.concat(newItems))或setItems(prev => [...prev, ...newItems]) - 避免直接
items.concat(newItems)后赋值,除非你手动管理可变状态(不推荐) - 如果后端返回分页信息(如
hasMore: true),建议把loading和hasMore也纳入状态管理,避免重复请求
性能优化:什么时候不该用 concat
当单次加载量大(如 >1000 条)、或滚动极快导致频繁拼接时,concat 会不断创建大数组,引发 GC 压力:
立即学习“Java免费学习笔记(深入)”;
- 可改用
Array.prototype.push(...newItems)配合useRef管理可变数组(仅限非响应式场景,如 Canvas 渲染) - 更推荐方案:用虚拟滚动(如
react-window)+ 分片缓存,只保留可视区附近数据,后台用 Map 或 IndexedDB 存全量 - 对历史数据做节流合并:例如每 3 次加载才拼一次,中间暂存到临时队列
防错处理:空数据、重复、边界情况
真实场景中,网络或接口异常会导致 newItems 不稳定:
- 始终校验
Array.isArray(newItems),避免null或对象误传导致静默失败 - 服务端若支持游标(cursor),比页码更可靠;前端可加简单去重逻辑:
[...new Set([...prev, ...newItems])](仅适用于 ID 可字符串化的场景) - 加载失败时,不要清空
prev,而是保持原状态,并提示用户“加载失败,点击重试”


















