打字稿RefForwardingComponent不起作用

Posted

技术标签:

【中文标题】打字稿RefForwardingComponent不起作用【英文标题】:Typescript RefForwardingComponent not working 【发布时间】:2020-03-18 09:01:48 【问题描述】:

我正在尝试让我的组件接受 ref。

我有一个这样的组件:

const MyComponent: RefForwardingComponent<htmlDivElement, IMyComponentProps> = (props, ref) => 
    return <div ref=ref>Hoopla</div>

但是当我尝试将 ref 传递给时是这样的:

<MyComponent ref=myRef></MyComponent>

...我收到此错误:

Property 'ref' does not exist on type 'IntrinsicAttributes & IMyComponentProps &  children?: ReactNode; '.ts(2322)

我做错了什么?

【问题讨论】:

【参考方案1】:

RefForwardingComponent 是一个render function,它接收 props 和 ref 参数并返回一个 React 节点 - 它是 no 组件:

第二个 ref 参数仅在您使用 React.forwardRef 调用定义组件时存在。常规函数或类组件不接收 ref 参数,并且 ref 在 props 中也不可用。 (docs)

这也是为什么RefForwardingComponent 是deprecated 而支持ForwardRefRenderFunction 的原因,这在功能上是等效的,但名称不同以使区别更清晰。

您使用React.forwardRef 将渲染函数转换为接受 refs 的实际组件:

import React,  ForwardRefRenderFunction  from 'react'

type IMyComponentProps =  a: string 
const MyComponentRenderFn: ForwardRefRenderFunction<HTMLDivElement, IMyComponentProps> =
    (props, ref) => <div ref=ref>Hoopla</div>

const MyComponent = React.forwardRef(MyComponentRenderFn);
const myRef = React.createRef<HTMLDivElement>();

<MyComponent a="foo" ref=myRef />

【讨论】:

【参考方案2】:

您的代码是正确的,但您遗漏了一个小细节。

使用RefForwardingComponent时需要导出forwardRef包裹的组件

import React,  forwardRef, RefForwardingComponent  from 'react';

type IMyComponentProps = 
const MyComponent: RefForwardingComponent<HTMLDivElement, IMyComponentProps> = (props, ref) => 
    return <div ref=ref>Hoopla</div>


export default forwardRef(MyComponent);

【讨论】:

OP 的问题是编译时类型错误。 forwardRef 不会修复它。缺少forwardRef 最终会导致运行时错误:Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?。所以 OP 确实需要 forwardRef,但他还没有做到那么远。 @Warren,你说得对,问题是编译时类型错误。 forwardRef 函数返回的类型是接受 ref 属性的类型。 ForwardRefExoticComponent&lt;PropsWithoutRef&lt;P&gt; &amp; RefAttributes&lt;T&gt;&gt; 这基本上包装了你的组件接受你的道具 (** PropsWithoutRef**) 和 'ref' 道具 (RefAttributes)【参考方案3】:

自定义函数组件不能将 'ref' 作为道具。你将不得不给它一个不同的名字。例如,'yourRef' 将在 props 对象内。

<MyComponent yourRef=myRef></MyComponent>

所以要使用 ref 属性:

const MyComponent: RefForwardingComponent<HTMLDivElement, IMyComponentProps> = (props) => 
return <div ref=props.yourRef>Hoopla</div>

或者你可以分解道具:

const MyComponent: RefForwardingComponent<HTMLDivElement, IMyComponentProps> = (yourRef) => 
return <div ref=yourRef>Hoopla</div>

【讨论】:

也许我弄错了,但我认为RefForwardingComponent 是假设让您的自定义组件接受参考?【参考方案4】:

我认为这是 React 的 RefForwardingComponent 类型定义中的一个错误。您可以通过将 ref?: React.RefObject&lt;HTMLDivElement&gt; 添加到您的道具来解决此问题。这将修复您的编译器错误。

试试这个:

type IMyComponentProps = 
    ref?: React.RefObject<HTMLDivElement>

我认为这个要求是一个错误,因为它应该由RefForwardingComponent 为您添加到道具中。把它放在你自己的道具中意味着 TypeScript 会期望你的函数中的 props 参数包含 ref 道具,我认为它不会。不过这不是什么大问题。

【讨论】:

以上是关于打字稿RefForwardingComponent不起作用的主要内容,如果未能解决你的问题,请参考以下文章

为我的反应打字稿组件库生成/维护打字稿定义文件

打字稿打字,打字文件夹是啥

打字稿 axios 打字

反应打字稿打字不起作用

打字稿:具有有效打字的“找不到模块”

如何在较新版本的打字稿中处理打字稿错误 Object.ts (7053)?