如何移除React列表项且不触发其他列表项重渲染?
解决列表项不必要重渲染的问题
问题根源
你当前的写法中,虽然给removeItem套了useCallback,但removeItem是一个返回新函数的高阶函数——每次调用removeItem(v.id)时,都会生成一个全新的箭头函数引用。这就导致每个<Item>组件的onClickRemove props始终是新值,memo判断props变化,所以所有列表项都会触发重渲染。
解决方案
调整逻辑,让所有<Item>共享同一个onClickRemove函数引用,点击时再传递对应项的id:
1. 修正类型定义
type IItem = { id: number; onClickRemove: (id: number) => void; };
2. 重构List组件的removeItem函数
直接让removeItem接收id参数,并用useCallback缓存这个函数本身,不再返回新函数:
const List = () => { const [list, setList] = useState<IItem[]>(initialList); const removeItem = useCallback((id: number) => { setList((prev) => prev.filter((v) => v.id !== id)); }, []); return list.map((v) => <Item id={v.id} onClickRemove={removeItem} key={v.id} />); };
3. 调整Item组件的点击逻辑
在Item内部的点击事件中,把当前项的id传递给onClickRemove:
const Item = memo((props: IItem) => { console.log(`Item #${props.id} rendered`); return ( <div> <a href="#" onClick={() => props.onClickRemove(props.id)}> Remove Item #{props.id} </a> </div> ); });
这样修改后,所有<Item>的onClickRemove props都是同一个函数引用,只有被删除的项会从列表中消失(不再渲染),其他项的props没有变化,memo会阻止它们的不必要重渲染,大幅提升大数据量下的操作性能。
内容的提问来源于stack exchange,提问作者Luvias
相关产品推荐
相关产品推荐

