首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何键入可以返回<a>或<button>并传递道具的Button组件

如何键入可以返回<a>或<button>并传递道具的Button组件
EN

Stack Overflow用户
提问于 2022-09-28 19:08:53
回答 2查看 87关注 0票数 1

试图构建一个组件,该组件将返回一个或一个基于"as“的道具。我还想把道具从任何标记呈现出来,以提供灵活性。

Problem --我似乎无法使类型正确,这样返回的元素就不会给出错误。下面是我的示例(简化):

代码语言:javascript
复制
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  as: "button";
}

interface AnchorProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
  as: "link";
}

const Button = ({
  children,
  as,
  ...restProps
}: AnchorProps | ButtonProps) => {

  if (as === "link") return <a {...restProps}>{children}</a>;

  if (as === "button") return <button {...restProps}>{children}</button>;

};

如果我移除联合类型并使用AnchorProps或ButtonProps,然后注释掉各自的if/return语句,它就可以正常工作。但是,一旦我将它与AnchorProps | ButtonProps结合起来,它就会给我HTML和标签上的错误,说类型不匹配。

我觉得我离得很近,但到不了那里。

EN

回答 2

Stack Overflow用户

发布于 2022-09-28 19:21:58

如果你把道具拆开,然后缩小一个道具,就很难知道道具是相连的。

相反,缩小props对象本身,然后将其拆分。

代码语言:javascript
复制
const Button = (props: (AnchorProps | ButtonProps)) => {
  if (props.as === "link") {
    const { as, ...restProps } = props
    return <a {...restProps}/>;
  }

  if (props.as === "button") {
    const { as, ...restProps } = props
    return <button {...restProps}/>;
  }

  return null
};

children也可以与...restProps一起传播。你不需要特殊情况来处理这件事,除非你出于某种原因想要拦截它。

见游乐场

票数 1
EN

Stack Overflow用户

发布于 2022-09-28 19:26:12

这将是最好的办法。您将在组件中获得最好的类型支持,因为它将根据您提供的...rest支持来确定什么是as支持。

代码语言:javascript
复制
import React, { ReactNode } from 'react';

type AnchorProps = React.AnchorHTMLAttributes<HTMLAnchorElement>;
type ButtonProps = React.ButtonHTMLAttributes<HTMLButtonElement>;

enum ButtonComponentType {
    LINK = 'link',
    BUTTON = 'button',
}

type ButtonComponentProps<T extends ButtonComponentType> = {
    as: T;
    children: ReactNode;
    // based on the "as" value, either intersect with ButtonProps or AnchorProps
} & (T extends ButtonComponentType.BUTTON ? ButtonProps : AnchorProps);

export function Button<T extends ButtonComponentType>({ children, as, ...restProps }: ButtonComponentProps<T>) {
    if (as === ButtonComponentType.LINK) return <a {...(restProps as AnchorProps)}>{children}</a>;
    if (as === ButtonComponentType.BUTTON) return <button {...(restProps as ButtonProps)}>{children}</button>;
    return null;
}

// neither of these throw an error
function Test1() {
    return (
        // doesn't have "href" because the "as" prop is set to "button"
        <Button as={ButtonComponentType.BUTTON} type="submit">
            <p>test</p>
        </Button>
    );
}

function Test2() {
    return (
        // doesn't have button props
        <Button as={ButtonComponentType.LINK} href="http://google.com">
            <p>test</p>
        </Button>
    );
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73886686

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档