【问题标题】:Type react component with changeable wrapper and wrapper props使用可变包装器和包装器道具键入反应组件
【发布时间】:2021-09-17 18:51:34
【问题描述】:

学习打字稿。 我正在尝试将类型添加到接受包装器组件的反应组件并将其余道具转发到包装器组件。但出现以下错误:

Type 'Pick<DirectProps<WrapperProps> & WrapperProps, Exclude<keyof WrapperProps, "as">> & { children: string; }' is not assignable to type 'IntrinsicAttributes & WrapperProps & { children?: ReactNode; }'.
  Type 'Pick<DirectProps<WrapperProps> & WrapperProps, Exclude<keyof WrapperProps, "as">> & { children: string; }' is not assignable to type 'WrapperProps'.
    'WrapperProps' could be instantiated with an arbitrary type which could be unrelated to 'Pick<DirectProps<WrapperProps> & WrapperProps, Exclude<keyof WrapperProps, "as">> & { children: string; }'

我无法解决。

小例子:

interface DirectProps<Props = unknown> {
  as?: string | React.ComponentType<Props>;
}

function GenericComponent<Props = unknown>({
  as: Component = "div",
  ...props
}: DirectProps<Props> & Props): JSX.Element {
  return <Component {...props}>Here goes children</Component>;
}

这样使用:

{/* Render as div */}
<GenericComponent onClick={() => console.log("Click")} />

{/* Render as link */}
<GenericComponent<React.AnchorHTMLAttributes<HTMLAnchorElement>>
  as="a"
  href="https://stackoverflow.com"
  target="_blank"
/>

我准备了代码框示例: https://codesandbox.io/s/sweet-hofstadter-2zzbe?file=/src/App.tsx

我会永远感激你的帮助

【问题讨论】:

    标签: reactjs typescript


    【解决方案1】:

    首先,你总是将一个字符串传递给道具as,所以我们可以将接口更改为:

    interface DirectProps {
      as?: string;
    } 
    

    之后我们可以把函数改成

    function GenericComponent<Props = React.HTMLAttributes<HTMLDivElement>>({
      as: Component = "div",
      ...props
    }: DirectProps & Props): JSX.Element {
      return <Component {...props}/>;
    }
    

    然后错误在您设置的代码沙箱中消失。

    抱怨的部分原因是您在Component 中添加了自己的孩子。孩子们将通过...props自动传递

    【讨论】:

    • 我想知道为什么它有帮助。约束Props 是否有帮助或其他什么。将as 切换为字符串不是一个选项,因为它可能是反应路由器Link
    【解决方案2】:

    我不确定您为什么要构建通用组件。我建议使用原子组件。如果每个组件的职责做好一件事,您的代码将更具可读性和更容易调试。问问自己:我到底想解决什么问题?我的代码的可读性和可调试性如何?我是否通过实现通用组件为自己节省了任何“思想复杂性”?我将如何对这些组件进行单元测试?

    以以下原子组件为例:

    // components/Links.tsx
    
    export function A(props: React.HTMLProps<HTMLAnchorElement>) {
      return (<a {...props} style={{ ...customStylesOrWhatever }} />)
    }
    export function LinkToHome() {
      return <A href="/home">Home</A>
    }
    export function LinkToSettings() {
      return <A href="/settings">Settings</A>
    }
    
    // "Dumb" components:
    <LinkToHome />
    <LinkToSettings />
    <A href="https://stackoverflow.com" target="_blank">StackOverflow</A>
    

    想象一下,在充满GenericComponent 的树中寻找特定组件。就个人而言,作为同事,我会非常沮丧。在具有数千个组件的应用程序中,这将需要大量的“大脑 RAM”。有了原子责任,这变成了一项微不足道的任务。这是关于组合与配置的决定,其中组合在 React 应用程序中通常是首选。

    【讨论】:

    • 虽然它没有回答最初的问题,但我很感谢你让我思考我是否真的需要这种可广泛配置的包装器。
    猜你喜欢
    • 1970-01-01
    • 2021-07-13
    • 2019-05-10
    • 1970-01-01
    • 2019-04-21
    • 2020-05-04
    • 1970-01-01
    • 1970-01-01
    • 2018-06-09
    相关资源
    最近更新 更多