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

如何用TypeScript实现带左右子组件的React复合组件?

在TypeScript中实现带Left/Right子组件的React组件

核心思路

通过组件引用判断或自定义静态标识,在父组件中遍历子节点,区分MyComponent.Left和MyComponent.Right对应的内容。

实现方案

方式1:直接通过组件引用判断(最简洁)

利用组件的引用关系直接区分,无需额外标识:

import React, { PropsWithChildren, ReactElement } from 'react';

type MyComponentProps = PropsWithChildren;

function MyComponent({ children }: MyComponentProps): JSX.Element {
  let leftContent: React.ReactNode = null;
  let rightContent: React.ReactNode = null;

  React.Children.forEach(children, (child) => {
    if (React.isValidElement(child)) {
      // 直接比较组件引用确定类型
      if (child.type === MyComponent.Left) {
        leftContent = child.props.children;
      } else if (child.type === MyComponent.Right) {
        rightContent = child.props.children;
      }
    }
  });

  return (
    <div style={{ display: 'flex', gap: '1rem' }}>
      <div className="this-goes-on-the-left">{leftContent}</div>
      <div className="this-goes-on-the-right">{rightContent}</div>
    </div>
  );
}

// 挂载Left子组件
MyComponent.Left = ({ children }: PropsWithChildren) => <>{children}</>;
// 挂载Right子组件
MyComponent.Right = ({ children }: PropsWithChildren) => <>{children}</>;

export default MyComponent;

方式2:通过静态属性标识(更具扩展性)

给子组件添加自定义静态属性,适合未来扩展更多子组件类型(如Header/Footer):

import React, { PropsWithChildren, ReactElement } from 'react';

type MyComponentProps = PropsWithChildren;

// 定义子组件类型,包含标识属性
interface MyComponentChild extends React.FC<PropsWithChildren> {
  componentType: 'left' | 'right';
}

function MyComponent({ children }: MyComponentProps): JSX.Element {
  let leftContent: React.ReactNode = null;
  let rightContent: React.ReactNode = null;

  React.Children.forEach(children, (child) => {
    if (React.isValidElement(child)) {
      const childComp = child.type as MyComponentChild;
      // 通过静态属性区分类型
      if (childComp.componentType === 'left') {
        leftContent = child.props.children;
      } else if (childComp.componentType === 'right') {
        rightContent = child.props.children;
      }
    }
  });

  return (
    <div style={{ display: 'flex', gap: '1rem' }}>
      <div className="this-goes-on-the-left">{leftContent}</div>
      <div className="this-goes-on-the-right">{rightContent}</div>
    </div>
  );
}

// 实现Left子组件并添加标识
const Left: MyComponentChild = ({ children }) => <>{children}</>;
Left.componentType = 'left';
MyComponent.Left = Left;

// 实现Right子组件并添加标识
const Right: MyComponentChild = ({ children }) => <>{children}</>;
Right.componentType = 'right';
MyComponent.Right = Right;

export default MyComponent;

使用示例

<MyComponent>
  <MyComponent.Left>
    foo
  </MyComponent.Left>
  <MyComponent.Right>
    bar
  </MyComponent.Right>
</MyComponent>

说明

  • 两种方案都能满足需求,方式1代码更简洁,方式2适合后续扩展更多子组件类型。
  • 父组件中通过React.Children.forEach遍历子节点,用React.isValidElement确保处理的是有效React元素。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 06:20:53