react 如何更新长列表
虚拟列表(Virtual List)
对于超长列表(如数千条数据),直接渲染所有DOM节点会导致性能问题。虚拟列表技术仅渲染可视区域内的元素,通过动态计算滚动位置更新显示内容。
实现方案:
-
react-window 或 react-virtualized 库提供开箱即用的虚拟列表组件。
-
示例代码(使用
react-window):import { FixedSizeList as List } from 'react-window'; const Row = ({ index, style }) => ( <div style={style}>Row {index}</div> ); const LongList = () => ( <List height={500} itemCount={1000} itemSize={35} width={300} > {Row} </List> );
分页加载(Pagination)
将长列表拆分为多页,用户滚动到底部时异步加载下一页数据。
关键点:
-
监听滚动事件,判断是否接近列表底部。
-
使用
useState或useReducer管理当前页数和加载状态。 -
示例代码:
const [items, setItems] = useState([]); const [page, setPage] = useState(1); const loadMore = () => { fetch(`/api/items?page=${page}`) .then(res => res.json()) .then(data => { setItems(prev => [...prev, ...data]); setPage(prev => prev + 1); }); }; useEffect(() => { loadMore(); }, []);
键值优化(Key Optimization)
确保列表项的 key 唯一且稳定,避免因 key 变化导致不必要的重新渲染。
建议:
- 使用数据中的唯一标识(如
id)而非数组索引。 - 示例:
{items.map(item => ( <div key={item.id}>{item.name}</div> ))}
不可变数据更新(Immutable Updates)
通过解构或库(如 immer)避免直接修改状态,减少不必要的渲染。
示例:
// 更新某项数据
setItems(prev => prev.map(item =>
item.id === updatedItem.id ? updatedItem : item
));
防抖/节流(Debounce/Throttle)
对频繁触发的更新(如搜索过滤)使用防抖或节流控制频率。
示例(使用 lodash):
import { debounce } from 'lodash';
const handleSearch = debounce((query) => {
setFilteredItems(items.filter(item => item.name.includes(query)));
}, 300);
性能监测工具
使用 React DevTools 和 Profiler 组件分析列表渲染性能,定位瓶颈。
示例:
import { Profiler } from 'react';
const onRender = (id, phase, duration) => {
console.log(`渲染耗时: ${duration}ms`);
};
<Profiler id="LongList" onRender={onRender}>
<LongList />
</Profiler>






