首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在React中,使用TypeScript,如何使用RefForwardingComponent和forwardRef将引用传递给自定义组件?

在React中,使用TypeScript,如何使用RefForwardingComponent和forwardRef将引用传递给自定义组件?
EN

Stack Overflow用户
提问于 2020-02-04 07:24:19
回答 1查看 22.8K关注 0票数 5

我正在尝试将一个参考文件传递给一个自定义组件(这样我就可以将焦点设置到组件上)。

但我一直在犯这个错误

代码语言:javascript
运行
复制
const RefComp: React.RefForwardingComponent<HTMLInputElement, Props>
Type '{ value: string; onChange: Dispatch<SetStateAction<string>>; ref: MutableRefObject<HTMLInputElement | undefined>; }'
is not assignable to type 'IntrinsicAttributes & Props & { children?: ReactNode; }'.
  Property 'ref' does not exist on type 'IntrinsicAttributes & Props & { children?: ReactNode; }'.ts(2322)

这是我的密码

代码语言:javascript
运行
复制
import * as React from 'react';
import {useRef, useState, RefForwardingComponent, forwardRef} from 'react';

interface Props {
    value: string;
    onChange(event: string): void;
}

const RefComp: RefForwardingComponent<HTMLInputElement, Props> = forwardRef<
    HTMLInputElement,
    Props
>(({value, onChange}, ref) => (
    <input
        value={value}
        onChange={event => onChange(event.target.value)}
        ref={ref}
    />
));

export default function App() {
    const [val, setVal] = useState('');
    const inputRef = useRef<HTMLInputElement>();

    return (
        <div className="App">
            <RefComp value={val} onChange={setVal} ref={inputRef} />
            <p>{val}</p>
        </div>
    );
}

这是一个代码框https://codesandbox.io/s/crimson-cdn-klfp5

如果我忽略了错误,那么代码似乎工作得很好。所以不知道我为什么要得到它..。

谁能解释一下我为什么会出错,以及我是如何修正的?)

编辑:

正如注释中提到的那样,您可以通过将ref添加到道具中来解决这一问题。

代码语言:javascript
运行
复制
import * as React from 'react';
import {
    useRef,
    useState,
    RefForwardingComponent,
    forwardRef,
    MutableRefObject,
} from 'react';

interface Props {
    value: string;
    onChange(event: string): void;
    ref?: MutableRefObject<HTMLInputElement | null>;
}

const RefComp: RefForwardingComponent<HTMLInputElement, Props> = forwardRef<
    HTMLInputElement,
    Props
>(({value, onChange}, ref) => (
    <input
        value={value}
        onChange={event => onChange(event.target.value)}
        ref={ref}
    />
));

export default function App() {
    const [val, setVal] = useState('');
    const inputRef = useRef<HTMLInputElement>(null);

    return (
        <div className="App">
            <RefComp value={val} onChange={setVal} ref={inputRef} />
            <p>{val}</p>
        </div>
    );
}

但这感觉不对。现在我们说ref既是道具的一部分,也是传递给forwardRef的函数的第二个回调参数

如果我这样写的话,我对这个问题的看法可能会更清楚。

代码语言:javascript
运行
复制
const RefComp: RefForwardingComponent<HTMLInputElement, Props> = forwardRef<
    HTMLInputElement,
    Props
>((props: Props, ref) => (
    <input
        value={props.value}
        onChange={event => props.onChange(event.target.value)}
        ref={ref /* here, props.ref is also available, but wouldn't work */ }
    />
));

编辑2:

下面是一个相关的问题

Typescript RefForwardingComponent not working

编辑3:

我找到了相关的源代码。https://github.com/DefinitelyTyped/DefinitelyTyped/blob/33f6179e0f25b0ca798ad89a667c0a27ea0c98dd/types/react/index.d.ts#L702

代码语言:javascript
运行
复制
function forwardRef<T, P = {}>(Component: RefForwardingComponent<T, P>): ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>;

因此,forwardRef函数返回类型为ForwardRefExoticComponent<PropsWithoutRef<P> & RefAttributes<T>>的组件。这是一个组件,它的道具类型为PropsWithoutRef<P>RefAttributes<T>相交。这两种类型也在同一个文件中定义。

据我所知,第一个基本不包括P中的ref (在我最初的示例中是Props )。第二个定义为

代码语言:javascript
运行
复制
interface RefAttributes<T> extends Attributes {
    ref?: Ref<T>;
}

考虑到这些信息,我真的不明白为什么要将ref添加到自己的Props中。看起来forwardRef真的应该为我做这件事--甚至从我自己的Props中移除ref .

有人能解释一下这是怎么回事吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-03-10 14:01:00

问题是RefComp的类型定义很差。删除它(让TypeScript推断类型),代码就可以正常工作了。

代码语言:javascript
运行
复制
import * as React from 'react';
import {useRef, useState, forwardRef} from 'react';

interface Props {
    value: string;
    onChange(event: string): void;
}

const RefComp = forwardRef<HTMLInputElement, Props>(
    ({value, onChange}, ref) => (
        <input
            value={value}
            onChange={event => onChange(event.target.value)}
            ref={ref}
        />
    ),
);

export default function App() {
    const [val, setVal] = useState('');
    const inputRef = useRef<HTMLInputElement>(null);

    React.useEffect(() => {
        if (inputRef.current) {
            inputRef.current.focus();
        }
    }, []);

    return (
        <div className="App">
            <RefComp value={val} onChange={setVal} ref={inputRef} />
            <p>{val}</p>
        </div>
    );
}

https://codesandbox.io/s/quizzical-liskov-bsruh

票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60052450

复制
相关文章

相似问题

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