React中map内PricedLayout组件重复渲染两次问题排查
React 遍历生成的轮播子组件重复渲染两次问题排查
核心原因
你在map外层加的console.log("testing")仅打印一次,已经排除了map函数重复执行的可能,重复渲染来自两个叠加的问题:
- 你使用的
Slider组件开启了infinite={true}配置。目前主流的React轮播库(比如react-slick)开启无限滚动模式时,会自动克隆首尾的若干个slide节点填充到轮播列表首尾,实现无缝衔接的滚动效果,这部分克隆的节点会额外挂载一次<PricedLayout />,是重复渲染的最主要来源。 - 列表key配置错误。你把
key={i}写在了<PricedLayout />内部的div上,没有绑定在map遍历返回的最外层组件标签上,React做列表diff时无法正确识别节点身份,会触发额外的重复挂载。
修复方案
处理轮播克隆节点问题
先在<PricedLayout />组件内部打印props验证:你会发现多渲染的组件实例上,会被Slider自动注入轮播相关的标记属性(比如isClone、aria-hidden、克隆节点专属的data属性),这是轮播组件的正常实现逻辑,不是代码逻辑错误。- 如果不需要无限轮播效果,直接把Slider的
infinite属性改为false,克隆的冗余节点会自动消失。 - 如果需要保留无限轮播效果,这部分重复挂载是实现无缝轮播的必要逻辑,不需要强行移除,只需要注意不要在
<PricedLayout />的挂载副作用(比如useEffect依赖为空的执行逻辑)里写重复埋点、全局状态修改这类逻辑即可,也可以通过判断组件是否是克隆节点,跳过非必要的副作用执行。
- 如果不需要无限轮播效果,直接把Slider的
修正列表key配置
把key属性从组件内部的DOM上挪到map返回的最外层<PricedLayout />标签上,同时不要用数组索引作为key,改用props.priced数据项里的唯一标识(比如试卷/商品的id字段)作为key,避免diff阶段的异常渲染:// 父组件遍历部分修正后代码 {props.priced.length && props.priced.map((p) => { // 替换成你数据里实际的唯一字段,比如p.testSeriesId return <PricedLayout key={p.id} p={p} /> })}同时清理子组件里的冗余代码:去掉没用的空Fragment包裹,删掉内部div上多余的key属性:
// PricedLayout修正后代码 const PricedLayout = (props) => { const { p } = props; return ( <div className={styles.slider}> <div className={styles.container}> <div className={styles.enroll}>1.2k students enrolled</div> </div> </div> ); }; export default PricedLayout;
内容的提问来源于stack exchange,提问作者Ajit Kumar
相关产品推荐
相关产品推荐

