我正在尝试将
useRef
与 TypeScript 一起使用,但遇到了一些问题。
用我的
RefObject
(我假设)我需要访问current
。 (即node.current
)
我尝试过以下方法
const node: RefObject<HTMLElement> = useRef(null);
const node = useRef<HTMLElement | null>(null);
但是当我去设置
ref
时,我总是被告知 X is not assignable to type 'LegacyRef<HTMLDivElement> | undefined'.
return <div ref={ node }>{ children }</div>
编辑:这不应限于任何一种类型的元素,因此不仅仅是
HTMLDivElement | HTMLFormElement | HTMLInputElement
编辑:这应该作为示例
import React, { useRef, RefObject } from 'react';
function Test()
{
// const node = useRef(null);
// const node: RefObject<HTMLElement> = useRef(null);
const node = useRef<HTMLElement | null>(null);
if (
node &&
node.current &&
node.current.contains()
){ console.log("current accessed")}
return <div ref={ node }></div>
}
以上方法都不适合我,但事实证明解决方案非常简单......
我做错的只是没有在 useRef 初始化中明确包含“null”作为参数(它需要 null,而不是未定义)。 另外,您不能使用“HTMLElement”作为您的引用类型,您必须更具体,所以对我来说它是“HTMLDivElement”)。
所以对我来说工作代码是这样的:
const ref = useRef<HTMLDivElement>(null);
return <div ref={ref}> Some Content... </div>
只需导入 React:
import React, { useRef } from 'react';
function Test() {
const node = useRef<HTMLDivElement>(null);
if (
node &&
node.current &&
node.current.contains()
){ console.log("current accessed")}
return <div ref={node}></div>
}
我更新了。使用
HTMLDivElement
作为通用参数而不是 HTMLElement | null
。另外,contains
期待一个争论。
更新
useRef
需要 DOM 元素类型的通用参数。您不需要使用 | null
,因为 RefObject
已经知道 current
可能为空。
参见下一个类型:
interface RefObject<T> {
readonly current: T | null
}
TS 和 React 足够聪明,可以发现你的 ref 可能为空
同样代表
<svg>
元素:
const ref = useRef<SVGSVGElement>(null)
...
<svg ref={ref} />
我来这里寻求 iframe 参考的帮助。也许这个解决方案会帮助其他正在寻找同样东西的人。我用
HTMLDivElement
替换了 HTMLIFrameElement
所以:
const node = useRef<HTMLIFrameElement>(null);
selfref = React.createRef<HTMLInputElement>()
我给出了准确的TS Type,然后编辑器通过了检查。现在效果很好。
作为解决方法,您可以显式强制转换:
const ref = useRef<HTMLDivElement>();
...
<input
ref={ref as RefObject<HTMLInputElement>}
...
/>
查看这里的所有答案后,我不确定他们中的任何一个是否完整地回答/解释了问题。在这种情况下,问题有两个:
React useRef 函数实际上有 3 个不同的签名(在 React 16.8 中):
如果传递的默认值与泛型类型相同
function useRef\<T>(initialValue: T): MutableRefObject<T>;
如果我们传递与泛型类型相同类型的默认值或 null(如此处许多响应所发现的)
function useRef\<T>(initialValue: T|null): RefObject<T>;
如果我们不传递默认值和/或我们不传递泛型类型
function useRef\<T = undefined>(): MutableRefObject<T | undefined>;
真正的问题归结为 MutableRefObject 和 LegacyRef 的不兼容。我猜测 React 团队对引用的数据类型进行了更改,因此我们根据我们传递的内容拥有多个签名和引用类型。
如果能从 React eslint 获得更好的错误消息那就太好了,至少因为我们收到的通用 TS 错误消息不足以立即发现问题所在。
Tl;dr:将 null 作为 useRef 对象中的默认值传递给我们返回同时满足 MutableRefObject 和 LegacyRef (可能)
的引用对象我有同样的错误,有人建议先转换为未知:
ref={inputRef as unknown as RefObject<HTMLTextAreaElement>}
关键是使用HTMLElement和undefined进行初始化
const node = useRef<HTMLElement>();
这里问题的根源不是你的 refObject 的类型(从
useRef()
返回的内容)。问题是 ref
prop 需要更具体的类型。
Div 的引用说:<div ref={..🗣"Give me HTMLDivElement!” 画布的参考:<canvas ref={..🗣"Give me HTMLCanvasElement!”`
例如,
<canvas>
的道具就像
// props of <canvas>
{
....
ref: {
current: HTMLCanvasElement
},
};
如您所见,它期望获得
HTMLCanvasElement
。
如果我们尝试传递父类(HTMLElement
),它会抱怨:“这对我来说还不够!它没有这样那样的属性!”
情况与此作业类似:
// ❌ Error, of course
const myElement: HTMLCanvasElement = new HTMLElement();
// (Type 'HTMLElement' is missing the following properties from type 'HTMLCanvasElement': captureStream, getContext, .....)
如果变量希望获得特定的值,您可以将什么“通用”值传递给变量?
— 无。
您甚至无法通过显式列出可能的选项来扩展其类型,例如
HTMLDivElement | HTMLFormElement | HTMLInputElement
,
const generalizedValue = getElement() as `HTMLDivElement | HTMLFormElement | HTMLInputElement`
// ❌ Nope! What if the passed object won't have "autofocus" or "placeholder" props ?!
const myCanvas: HTMLCanvasElement = generalizedValue;
// ❌ Nope! What if the passed object won't be able to captureStream() ?!
const myInput: HTMLInputElement = generalizedValue;
您想让您的 ref 通用 - 所以它可能是在某些可重用的自定义挂钩中创建的。请毫不犹豫地在其中指定自定义泛型!
这就是父类派上用场的地方! —
<T extends HTMLElement>
!
const useMyCoolHook = <ElType extends HTMLElement>() => {
const elRef = useRef<ElType>(null);
//...your logic goes here...
return elRef;
}
function MyButton()
{
const firstButtonRef = useMyCoolHook<HTMLButtonElement>(null); //<-- for <button>
const anotherButtonRef = useMyCoolHook<HTMLButtonElement>(null); //<-- for <button>
const linkRef = useMyCoolHook<HTMLAnchorElement>(null); //<-- for <a>
return (
<>
<button ref={ firstButtonRef } />
<button ref={ anotherButtonRef } />
<a ref={ linkRef } />
</>
);
}
如果在大多数情况下它将与一种特定类型的元素一起使用(例如,与
<div>
s),您可以将其设为通用的默认值:<ElType extends HTMLElement = HTMLDivElement>
const useMyCoolHook = <ElType extends HTMLElement = HTMLDivElement>() => {
....
您在打字稿中收到此错误的原因是因为您需要输入 ref.current 而不仅仅是 ref
示例:
const ref = React.useRef<HTMLDivElement>(null);
Component(props: {ref?: {current: HTMLDivElement}})