You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React嵌套map渲染组件报key prop缺失/重复错误解决方法

问题根因

Each child in a list should have a unique "key" prop警告的触发原因是:所有通过Array.map()生成的列表直接子元素,都必须传入在当前同级节点下唯一的key属性。之前加key出现重复,大概率是key只使用了单层数组的索引,跨层级时索引值撞重,或是key错加在了嵌套子元素上、没有加在map返回的最外层节点上。

必须添加key的节点

代码一共有三层嵌套map,每一层map返回的最外层元素都需要加key,key只需要保证和同一父节点下的其他兄弟节点不重复即可,不需要全局唯一:

  • 第一层:renderComponentFamilies方法中遍历componentFamilies的map,两个条件分支返回的最外层节点(多组件分支的Grid项、单组件分支的Fragment)
  • 第二层:renderComponents方法中遍历components的map,返回的最外层Grid项
  • 第三层:renderCourseRequirements方法中遍历courseList的map,返回的最外层Grid项

注意:单组件分支使用的空标签<>...</>是简写版Fragment,不支持传入属性,需要改成完整写法React.Fragment才能绑定key。

key赋值方案(避免重复)

优先使用业务自带的唯一标识作为key,渲染稳定性比单纯用数组索引更高,拼接父级标识就能完全避免跨层重复:

  • 组件族层:优先用组件族ID,没有的话用${componentFamily.component_family_name}-${index}
  • 组件层:优先用组件ID,没有的话用${component.component_name}-${父级组件族标识}-${index}
  • 课程层:优先用课程ID,没有的话用${course}-${父级组件标识}-${index}
修正后完整代码
import React from 'react';

const renderCourseRequirements = (courseList, componentId) => {
  return (
    <Grid>
      {/* 第三层map:给返回的最外层Grid加key */}
      {courseList.map((course, index) => {
        return (
          <Grid 
            item 
            xs={12} 
            sm={6} 
            md={4}
            key={`course-${componentId}-${course}-${index}`}
          >
            <Card sx={{ width: 200 }} variant="outlined">
              <CardContent>
                <Typography color="textSecondary" gutterBottom>
                  {course}
                </Typography>
                <Checkbox name={course}></Checkbox>
              </CardContent>
            </Card>
          </Grid>
        );
      })}
    </Grid>
  );
};

const renderComponents = (components, familyId) => {
  return (
    <Grid justify="center">
      {/* 第二层map:给返回的最外层Grid加key */}
      {components.map((component, index) => {
        const componentId = `${familyId}-${component.component_name}-${index}`;
        return (
          <Grid 
            item 
            xs={12} 
            sm={6} 
            md={4}
            key={componentId}
          >
            <Card className={classes.root} variant="outlined">
              <CardContent>
                <Typography
                  className={classes.title}
                  color="textSecondary"
                  gutterBottom
                >
                  {component.component_name}
                </Typography>
                <Typography className={classes.pos} color="textSecondary">
                  Required Number of Courses: {component.required_num_courses}
                </Typography>
                {/* 传入当前组件标识给下一层,避免key重复 */}
                {renderCourseRequirements(component.course_list, componentId)}
              </CardContent>
            </Card>
          </Grid>
        );
      })}
    </Grid>
  );
};

const renderComponentFamilies = (componentFamilies) => {
  return (
    <Grid
      container
      spacing={4}
    >
      {/* 第一层map:给两个分支返回的最外层节点加key */}
      {componentFamilies.map((componentFamily, index) => {
        const familyId = `${componentFamily.component_family_name}-${index}`;
        if (componentFamily.component_list.length > 1)
          return (
            <Grid 
              item 
              xs={12} 
              sm={6} 
              md={4}
              key={familyId}
            >
              <Card className={classes.root} variant="outlined">
                <CardContent>
                  <Typography
                    className={classes.title}
                    color="textSecondary"
                    gutterBottom
                  >
                    {componentFamily.component_family_name}
                  </Typography>
                  <Typography className={classes.pos} color="textSecondary">
                    Required Number of Components :{" "}
                    {componentFamily.required_num_components}
                  </Typography>
                  {renderComponents(componentFamily.component_list, familyId)}
                </CardContent>
              </Card>
            </Grid>
          );
        return (
          // 空Fragment改成完整写法以支持key属性
          <React.Fragment key={`single-${familyId}`}>
            <Grid item xs={12} sm={6} md={4}>
              {renderComponents(componentFamily.component_list, familyId)}
            </Grid>
          </React.Fragment>
        );
      })}
    </Grid>
  );
};

内容的提问来源于stack exchange,提问作者Jackie Dong

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 02:27:18