React组合模式下,是否需用useMemo包裹作为Props传递的组件?
问题1:不使用useMemo时,渲染阶段真的会执行吗?
是的,肯定会执行。当你直接把<><TitleComponent prop={value} /><TitleComponent prop={value} /></>作为title props传给Template组件时,每次父组件重渲染,这个JSX片段都会被重新创建——本质上这是一个全新的React Fragment元素对象。
如果Template组件没对title props做记忆化处理(比如没包React.memo,也没在内部用useMemo缓存这个props),那每次父组件渲染,Template都会收到一个全新的title引用,进而触发对应部分的重渲染:包括创建TitleComponent的实例、执行它们的函数体(函数组件)或render方法(类组件),也就是完整的渲染阶段流程都会走一遍。
哪怕TitleComponent自己用了React.memo,只要外层的Fragment是新创建的,作为props传入Template后,React对比新旧元素引用时会发现不一样,还是会重新处理这部分子树的渲染逻辑。
问题2:用useMemo包裹作为Props的组件是否有实际作用?
有实际作用,但要结合场景来看:
核心价值:跳过不必要的渲染阶段
用useMemo包裹这个JSX片段后,只要依赖数组[deps]里的变量没变化,useMemo就会返回之前缓存的React元素引用。如果Template组件做了记忆化优化(比如用React.memo包裹,内部对titleprops做了引用相等性检查),那Template就不会因为title的变化触发重渲染,连带着TitleComponent的渲染阶段也会被直接跳过——这就是你同事说的“跳过渲染阶段”,而不是只跳过提交阶段(提交阶段是DOM更新,就算渲染阶段输出和之前一致,提交阶段会跳过DOM操作,但渲染阶段本身已经执行过了)。场景限制
如果Template组件本身没做记忆化(比如没包React.memo,也没在内部处理title的缓存),那useMemo包裹title的作用就很有限——因为Template每次都会重渲染,就算title引用没变,它还是会把title对应的子元素再渲染一遍(不过此时React的diff算法会发现子元素和之前完全一致,最终跳过DOM更新,但渲染阶段的逻辑已经跑过了)。
补充一句:Kent C. Dodds文章里说的“仅将组件作为Props传递就已完成优化”,应该是针对组件作为子组件插槽传递且父组件做了记忆化的场景,而你这里是把React元素作为title props传递,和插槽的处理逻辑有区别,不能直接套用这个结论。
内容的提问来源于stack exchange,提问作者Woojin Lee

