如何用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
相关产品推荐
相关产品推荐

