如何使用React.memo避免新增组件元素时触发重复渲染?
解决方案
1. 保证旧消息的引用稳定
父组件新增消息时,要保留原有消息对象的引用,仅追加新消息对象。推荐使用useState的函数式更新:
// 父组件逻辑 const [api_res, setApiRes] = useState([]); const addNewMsg = (newMsg) => { // 通过prevState获取旧数组,只添加新元素,旧元素引用完全保留 setApiRes(prev => [...prev, newMsg]); };
如果是从接口拉取消息,要确保旧消息的对象引用和之前一致,避免重新生成所有旧消息的新对象。
2. 给MemoMsg的props添加稳定引用
如果给MemoMsg传递了回调函数、对象这类易变的props,必须用useCallback或useMemo缓存,避免每次渲染生成新引用:
// 父组件中缓存回调函数 const handleMsgAction = useCallback((msgTimestamp) => { // 具体处理逻辑 }, []); // 依赖为空时,函数只会创建一次 // 在MsgList中传递给MemoMsg <MemoMsg key={msg.timestamp} msg={msg} onAction={handleMsgAction} />
3. 给MemoMsg自定义props比较逻辑
默认的React.memo是浅比较,若props包含复杂对象,可自定义比较函数,确保只有内容真正变化时才重新渲染:
const MemoMsg = React.memo(MsgComponent, (prevProps, nextProps) => { // 按需比较关键属性,判断是否需要复用组件 return prevProps.msg.timestamp === nextProps.msg.timestamp && prevProps.msg.content === nextProps.msg.content && prevProps.onAction === nextProps.onAction; });
4. 移除MsgList的React.memo包装
React.memo包装的MsgList作用有限——新增消息时api_res必然是新数组,MsgList一定会重新执行。优化重点应放在MemoMsg的缓存上,所以可以直接去掉MsgList的React.memo包装:
function MsgList({ api_res}) { return api_res.map((msg) => { return ( <MemoMsg key={msg.timestamp} msg={msg} // 其他稳定props /> ); }); }
调整后,新增消息时只有新的MemoMsg组件会被渲染,旧组件因props无变化(引用稳定、比较逻辑通过)会被直接复用,不会重新渲染。
内容的提问来源于stack exchange,提问作者Bear Bile Farming is Torture
相关产品推荐
相关产品推荐

