繁体   English   中英

Typescript,如何判断一个变量是哪个React函数组件?

[英]In Typescript, how can I tell which React functional component a variable is?

我有一个CustomIcon组件,有时用于我的图标,有时我使用 MUI 的图标。 我有一个变量定义为的类型:

type ParentComponentProps = {
  icon: React.ReactElement<SvgIconProps> | typeof CustomIcon;
};

这样,我可以这样调用ParentComponent

<ParentComponent icon={<HomeIcon />}/>

要么

<ParentComponent icon={<CustomIcon {...args}/>}/>

我想要一种方法来确定icon是使用 MUI 图标还是我的CustomIcon的值。 ParentComponent中,我想将 arguments 添加到传入的icon中,这样消费者就不必这样做(例如,除了消费者可能指定的内容之外,我还想添加className类)。

我尝试了各种方法来解决这个问题,使用typeofinstanceofReturnType但它们通常都受到限制,因为需要比较值而不是类型。

有没有办法使用条件来解决这个问题,还是需要另一种方式来解决?

创建的 React 组件的类型(格式为<Icon /> )总是JSX.Element ,如果你需要一些类型检查,你应该将组件本身传递给 props

所以组件道具将如下所示,请注意名称更改为Icon因为如果你在里面做<icon /> ,它会认为你正在尝试使用原生元素调用icon

type ParentComponentProps = {
  Icon: React.ComponentType<SvgIconProps> | typeof CustomIcon;
};

但通常我会让CustomIcon的道具(假设它被称为CustomIconProps )与SvgIconProps兼容,并且类型将是:

type CustomIconProps = SvgIconProps & {
// ...
};

type ParentComponentProps = {
  Icon: React.ComponentType<SvgIconProps>;
};

这会更清楚。

和用法:

<ParentComponent Icon={HomeIcon}/>
<ParentComponent Icon={CustomIcon}/>

如果您需要将args传递给CustomIcon

<ParentComponent Icon={(props: CustomIconProps) => <CustomIcon {...props} {...args}/>}/>

我想要一种方法来确定图标的值

你想在哪里使用它?

如果您需要它来确定另一种类型,例如键入style道具,您可以这样做:

      type SvgIcon = React.ReactElement<SvgIconProps>

      type ParentComponentProps<Icon extends  SvgIcon | typeof CustomIcon> = {
               icon: Icon;
               style: Icon extends SvgIcon ? Type1 : Type2
        
       };

即使你这样做:

<ParentComponent
  icon={<CustomIcon {...args}/>}
/>

...您实际上是将ReactElement传递给icon道具。

更一般地说,这类似于children道具或任何插槽内容道具。 我们通常将它们键入为ReactNode ,它也接受一个string null或一个ReactNode数组。

确实可以从ReactElement中判断它是由哪个组件构建的,通常是通过查看其type.name属性,但您需要首先保护它,如Accessing child.type.name in React Typescript 中所述

function ParentComponent({
    icon
}: {
    icon: React.ReactElement
}) {
    if (React.isValidElement(icon) && typeof icon.type === "function") {
        icon.type.name // Okay
    }
    return <></>
}

游乐场链接

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM