使用React.memo避免长列表未变更项重渲染的异常问题排查
问题原因
你遇到的异常是点击任意一项的Add按钮后,所有列表项都会触发重渲染,控制台会打印所有id的Rendering -> xxx日志,没有达到仅渲染修改项的优化预期。核心原因有两点:
- 列表渲染时未添加唯一
key属性:React渲染列表时依赖唯一key标识每个组件实例,用来判断哪些实例可以复用、哪些需要更新。未显式指定key时React会默认用索引作为key,每次list状态变更后都会全量重渲染所有列表项。 onAdd函数引用不稳定:onAdd定义在App组件内部,每次list状态更新触发App重渲染时,都会生成新的onAdd函数实例,传递给所有Item的onChange属性都是新的。如果后续调整React.memo的比较逻辑为默认浅比较,这个问题仍会触发全量重渲染。
修复方案
按以下步骤修改即可实现仅修改项重渲染:
- 给列表项添加唯一
key属性,取值为item的id:
{list.map((item) => ( <Item key={item.id} {...item} onChange={onAdd} /> ))}
- 用
useCallback包裹onAdd函数,同时将setList改为函数式更新,避免依赖外部的list变量,保证onAdd的引用永远稳定:
import React, { useState, useCallback } from "react"; // 省略其他代码 const onAdd = useCallback((id, qtd) => { setList(prevList => prevList.map((item) => { if (item.id === id) { return { ...item, qtd }; } return item; })); }, []);
- 完善
areEqual比较逻辑,增加id校验避免极端场景下的props错位:
function areEqual(prev, next) { return prev.id === next.id && prev.qtd === next.qtd; }
修改完成后点击任意项的Add按钮,仅当前修改的列表项会触发重渲染,其余未修改项不会产生多余渲染。
内容的提问来源于stack exchange,提问作者rayashi
相关产品推荐
相关产品推荐

