React中map循环内的memo组件在数组元素更新时是否全量重渲染?
React.memo子组件在数组局部更新时的重渲染问题
假设我们有一个经过React.memo包裹的Child组件(修正了原代码的语法错误):
function Child({ number }) { return <div>{number}</div>; } export default React.memo(Child);
该Child组件仅在number props变化时才会重渲染。
将该Child组件放入Parent组件中(修正了原代码的语法错误):
import { useState } from 'react'; import Child from './Child'; function Parent() { const [numbers, setNumbers] = useState([1,2,3,4,5,6]); return ( <> {numbers.map((number, index) => { return <Child key={index} number={number} />; })} </> ); }
此时Child组件通过遍历numbers数组生成,且已被memo化。如果仅修改数组中的一个元素,例如通过setNumbers将[1,2,3,4,5,6]改为[1,2,111111,4,5,6](第三个元素从3变为111111),请问是所有Child组件都会重渲染,还是仅第三个Child组件会重渲染?
回答
仅第三个Child组件会重渲染,其余Child组件不会触发重渲染。
具体原因:
- 当
numbers数组更新时,Parent组件会触发重渲染,重新执行render逻辑生成新的Child元素列表; - React会通过
key来匹配新旧Child组件实例:- 对于key为0、1、3、4、5的Child组件,它们的
numberprops和更新前完全一致(分别是1、2、4、5、6); - 由于Child组件被
React.memo包裹,它会对新旧props做浅比较,当props未发生变化时,会跳过重渲染流程;
- 对于key为0、1、3、4、5的Child组件,它们的
- 只有key为2的Child组件,
numberprops从3变为111111,props发生了明确变化,因此会触发重渲染。
注意:使用index作为组件key确实存在弊端,但仅在插入、删除数组元素的场景下会导致大量不必要的重渲染(比如在数组开头插入元素,后续所有Child的key会和原有实例不匹配,React会销毁旧组件并创建新组件,即使props内容未变)。但在本次问题的场景中,只是修改数组某一元素的值,所有Child的key与原有实例一一对应,因此不会出现这种问题。
内容的提问来源于stack exchange,提问作者Rongeegee
相关产品推荐
相关产品推荐

