在 TypeScript 中使用带有子项的 forwardRef 组件

新手上路,请多包涵

使用 @types/react 16.8.2 和 TypeScript 3.3.1。

我直接从 React 文档 中提取了这个 forward refs 示例,并添加了几个类型参数:

 const FancyButton = React.forwardRef<HTMLButtonElement>((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// You can now get a ref directly to the DOM button:
const ref = React.createRef<HTMLButtonElement>();
<FancyButton ref={ref}>Click me!</FancyButton>;

我在 FancyButton 下的最后一行收到以下错误:

类型“ { children: string; ref: RefObject<HTMLButtonElement>; } ”不可分配给类型“ IntrinsicAttributes & RefAttributes<HTMLButtonElement> ”。属性’ children ‘不存在于类型’ IntrinsicAttributes & RefAttributes<HTMLButtonElement> ‘.ts(2322)

React.forwardRef 的返回值的类型定义似乎是错误的,没有正确合并 children 道具。如果我使 <FancyButton> 自动关闭,错误就会消失。缺少此错误的搜索结果使我相信我遗漏了一些明显的东西。

原文由 trevorsg 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.5k
2 个回答

trevorsg,您需要传递按钮属性:

 import * as React from 'react'

type ButtonProps = React.HTMLProps<HTMLButtonElement>

const FancyButton = React.forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => (
  <button type="button" ref={ref} className="FancyButton">
    {props.children}
  </button>
))

// You can now get a ref directly to the DOM button:
const ref = React.createRef<HTMLButtonElement>()

<FancyButton ref={ref}>Click me!</FancyButton>

添加:

在最新版本的 TS 和 @types/react 中,您还可以使用 React.ComponentPropsWithoutRef<'button'> 代替 React.HTMLProps<HTMLButtonElement>

原文由 aMarCruz 发布,翻译遵循 CC BY-SA 4.0 许可协议

aMarCruz 和 euvs 给出的答案都是有效的,只是有点欺骗了消费者。他们说他们接受所有 HTMLButtonElement 道具,但他们忽略它们而不是将它们转发给按钮。如果你只是想正确地合并 children 道具,那么你可能想改用 React.PropsWithChildren :

 import React from 'react';

interface FancyButtonProps {
    fooBar?: string; // my custom prop
}

const FancyButton = React.forwardRef<HTMLButtonElement, React.PropsWithChildren<FancyButtonProps>>((props, ref) => (
    <button type="button" ref={ref} className="fancy-button">
        {props.children}
        {props.fooBar}
    </button>
));

FancyButton.displayName = 'FancyButton';

或者显式添加一个 children 道具:

 interface FancyButtonProps {
    children?: React.ReactNode;
    fooBar?: string; // my custom prop
}

const FancyButton = React.forwardRef<HTMLButtonElement, FancyButtonProps>((props, ref) => (
    <button type="button" ref={ref} className="fancy-button">
        {props.children}
        {props.fooBar}
    </button>
));

FancyButton.displayName = 'FancyButton';

或者如果你真的想接受所有的按钮道具并转发它们(例如让消费者选择按钮类型=“提交”),那么你可能想要使用 rest/spread:

 import React from 'react';

interface FancyButtonProps extends React.ComponentPropsWithoutRef<'button'> {
    fooBar?: string; // my custom prop
}

const FancyButton = React.forwardRef<HTMLButtonElement, FancyButtonProps>(
    ({ children, className = '', fooBar, ...buttonProps }, ref) => (
        <button {...buttonProps} className={`fancy-button ${className}`} ref={ref}>
            {children}
            {fooBar}
        </button>
    ),
);

FancyButton.displayName = 'FancyButton';

原文由 Dan Stoppelman 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进