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

React组件遍历子元素的子节点报错?求正确实现方案

问题描述

我有一个可接收单个或多个子元素的组件,用法如下:

接收多个子元素的情况

<SideDataGridItem>
   <div id='top'>
      <div>A1</div>
      <div>B1</div>
      <div>C1</div>
   </div>
   <div id='bottom'>
       <div>A2-</div>
       <div>B2-</div>
       <div>C2-</div>
    </div>
 </SideDataGridItem>

接收单个子元素的情况

<SideDataGridItem>
   <div id='top'>
      <div>A1</div>
      <div>B1</div>
      <div>C1</div>
   </div>
 </SideDataGridItem>

我希望遍历这些子元素的子节点,最终输出不需要包含id为top或bottom的div,只需要渲染它们的子节点(比如A1、B1这类)。

失败的尝试1

import { ReactElement, Children } from 'react';

export interface PropsShape {
  children: ReactElement | ReactElement[];
}

const SideDataGridItem = ({ children }: PropsShape): ReactElement => {
  const childArr = Children.toArray(children);
  return (
    <>
      {childArr[0] &&
        childArr[0].map(function (item: any, i: number) {
          return (
            <div key={i}>
              {item}- {i}
            </div>
          );
        })}
      {childArr[1] &&
        childArr[1].map(function (item: any, i: number) {
          return (
            <div key={i}>
              {item}- {i}
            </div>
          );
        })}
    </>
  );
};
export { SideDataGridItem };

报错:

Property 'map' does not exist on type 'ReactChild | ReactFragment | ReactPortal'.
  Property 'map' does not exist on type 'string'.

失败的尝试2

import { ReactElement, Children } from 'react';

export interface PropsShape {
  children: ReactElement | ReactElement[];
}

const SideDataGridItem = ({ children }: PropsShape): ReactElement => {
  const childArr = Children.toArray(children);
  return (
    <>
    // map over the childArr
      {childArr.map(function (item: any) {
        // for each item inside the childArr map over them ?? expecting just 3 items not 4 or 1
        {
          item.map(function (itemInner: any, i: number) {
            return (
              <div key={i}>
                {itemInner}- {i}
              </div>
            );
          });
        }
      })}
    </>
  );
};
export { SideDataGridItem };

失败的尝试3

打印childArr后发现目标子节点在childArr[0].props.children中,尝试遍历:

{childArr[0] &&
        childArr[0].props.children.map(function (item: any, i: number) {
          return (
            <div key={i}>
              {item}- {i}
            </div>
          );
        })}

报错:

Property 'props' does not exist on type 'ReactChild | ReactFragment | ReactPortal'.
  Property 'props' does not exist on type 'string'.

解决方案

问题核心在于TypeScript的类型限制:Children.toArray(children)返回的数组元素类型是ReactChild | ReactFragment | ReactPortal,直接访问props或调用map会因为类型不明确报错。需要先校验元素类型,再安全处理子节点。

最终实现代码:

import { ReactElement, Children, isValidElement } from 'react';

export interface PropsShape {
  children: ReactElement | ReactElement[];
}

const SideDataGridItem = ({ children }: PropsShape): ReactElement => {
  const childElements = Children.toArray(children);
  
  return (
    <>
      {childElements.map((parentChild, parentIndex) => {
        // 校验当前元素是否为React合法元素
        if (isValidElement(parentChild)) {
          // 将目标子节点统一转为数组处理
          const innerChildren = Children.toArray(parentChild.props.children);
          
          return innerChildren.map((item, i) => (
            <div key={`${parentIndex}-${i}`}>
              {item}- {i}
            </div>
          ));
        }
        // 非React元素直接返回(比如文本节点)
        return parentChild;
      })}
    </>
  );
};

export { SideDataGridItem };

代码说明

  1. 类型校验:通过isValidElement判断子元素是否为React元素,避免访问props时触发类型错误。
  2. 统一处理子节点:用Children.toArray将每个父元素的子节点转为数组,兼容单个或多个子节点的场景。
  3. 唯一key:组合父元素索引与子元素索引生成唯一key,避免渲染时出现重复key警告。

这样无论组件接收单个还是多个子元素,都能正确遍历并渲染它们的子节点,且不会输出外层的top/bottom容器div。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 18:40:29