在TypeScript中将forwardRef组件与子代一起使用

tre*_*rsg 8 jsx typescript reactjs tsx

使用@ types / react 16.8.2和TypeScript 3.3.1。

我直接从React文档中提出了这个前向引用示例,并添加了几个类型参数:

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>;
Run Code Online (Sandbox Code Playgroud)

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

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

看来React.forwardRef的返回值的类型定义是错误的,没有正确地合并在子道具中。如果我<FancyButton>自行关闭,错误就会消失。缺少针对该错误的搜索结果,使我相信自己缺少明显的东西。

小智 8

aMarCruz 给出的答案效果很好。但是,如果您还需要将自定义道具传递给FancyButton,这里是如何做到的。

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

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


/// Use later

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

<FancyButton ref={ref} fooBar="someValue">Click me!</FancyButton>

Run Code Online (Sandbox Code Playgroud)

只需在此处添加即可完成。


Dan*_*man 7

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';
Run Code Online (Sandbox Code Playgroud)

或者明确添加一个 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';
Run Code Online (Sandbox Code Playgroud)

或者,如果您确实想接受所有按钮道具并转发它们(例如,让消费者选择按钮类型 =“提交”),那么您可能需要使用 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';
Run Code Online (Sandbox Code Playgroud)


aMa*_*ruz 6

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>
Run Code Online (Sandbox Code Playgroud)

添加:

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

  • 我讨厌TS这样的事情 (7认同)

归档时间:

查看次数:

2722 次

最近记录:

6 年,6 月 前