将 useRef 与 TypeScript 一起使用的问题
Posted
技术标签:
【中文标题】将 useRef 与 TypeScript 一起使用的问题【英文标题】:Issue using useRef with TypeScript 【发布时间】:2020-11-17 01:10:39 【问题描述】:我有以下代码;
App.tsx
export default function App()
const [canvasRef, canvasWidth, canvasHeight] = useCanvas();
return (
<div>
<canvas
ref=canvasRef
/>
</div>
)
useCanvas.ts
import useRef, useEffect from "react";
const canvasWidth = 1200;
const canvasHeight = 600;
export default function useCanvas()
const canvasRef = useRef<htmlCanvasElement>(null);
return [canvasRef, canvasWidth, canvasHeight]
是的,这正是我的代码中的内容,但是,我在来自 Vscode 的 App.tsx 中收到以下错误;
(JSX attribute) React.ClassAttributes<HTMLCanvasElement>.ref?: string | React.RefObject<HTMLCanvasElement> | ((instance: HTMLCanvasElement | null) => void) | null | undefined
Type 'number | RefObject<HTMLCanvasElement>' is not assignable to type 'string | RefObject<HTMLCanvasElement> | ((instance: HTMLCanvasElement | null) => void) | null | undefined'.
Type 'number' is not assignable to type 'string | RefObject<HTMLCanvasElement> | ((instance: HTMLCanvasElement | null) => void) | null | undefined'.ts(2322)
index.d.ts(143, 9): The expected type comes from property 'ref' which is declared here on type 'DetailedHTMLProps<CanvasHTMLAttributes<HTMLCanvasElement>, HTMLCanvasElement>'
任何建议将不胜感激。
【问题讨论】:
检查类似的问题,这可能会帮助你***.com/questions/33796267/… 【参考方案1】:function useCanvas()
const canvasRef = useRef<HTMLCanvasElement>(null);
return [canvasRef, canvasWidth, canvasHeight]
由于您没有为返回值指定类型,因此打字稿会推断它。在推断数组的类型时,打字稿会假定它是一个普通数组,而不是 tuple。
为简化起见,假设您要返回以下内容:
function ()
return [1, 'a'];
Typescript 会推断类型为(number | string)[]
。换句话说,一个任意长度的数组,其中每个元素都可以是字符串的数字。它不会推断类型为[number, string]
。因此,如果您尝试与该数组的索引 0 进行交互,打字稿将无法告诉您它绝对是一个数字,只能告诉您它是一个数字或字符串。
所以你的第一个选择是给你返回的东西一个明确的类型。在我的简化案例中,它将是:
function ()
const result: [number, string] = [1, 'a'];
return result;
// or
function (): [number, string]
return [1, 'a'];
// or
function ()
return [1, 'a'] as [number, string];
我不确定您的代码是否正确的类型,但您可以检查变量并找出答案。
另一种选择,可能是更简单的选择,是使用as const
来帮助 typescript 推断类型。 as const
告诉它这永远不会改变,因此它会将其视为元组而不是数组。
function useCanvas()
const canvasRef = useRef<HTMLCanvasElement>(null);
return [canvasRef, canvasWidth, canvasHeight] as const;
【讨论】:
完美,谢谢!一开始我不确定这是否只是一个 linting 错误,但这更有意义。【参考方案2】:你的自定义钩子的返回类型是(number | React.MutableRefObject<HTMLCanvasElement>)[]
,因为打字稿推断它返回一个包含这些类型的数组。这就是为什么 App.tsx
中的解构变量没有正确键入(如果将它们悬停,您会看到它们都是 number | React.MutableRefObject<HTMLCanvasElement>
类型)。
你需要的是使用一个元组来告诉 typescript 这个数组中到底包含什么。
您可以像这样将输入信息添加到您的自定义挂钩中:
import useRef, useEffect, MutableRefObject from "react";
const canvasWidth = 1200;
const canvasHeight = 600;
export default function useCanvas(): [MutableRefObject<HTMLCanvasElement>, number, number]
const canvasRef = useRef<HTMLCanvasElement>(null);
return [canvasRef, canvasWidth, canvasHeight]
【讨论】:
以上是关于将 useRef 与 TypeScript 一起使用的问题的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Typescript 中将 ref prop 和 useRef 与 Lottie 文件一起使用?
useRef TypeScript - 不可分配给类型 LegacyRef<HTMLDivElement>
React - useRef 与 TypeScript 和功能组件