【问题标题】:Issue using useRef with TypeScript将 useRef 与 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>'

任何建议将不胜感激。

【问题讨论】:

标签: javascript reactjs typescript


【解决方案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&lt;HTMLCanvasElement&gt;)[],因为打字稿推断它返回一个包含这些类型的数组。这就是为什么 App.tsx 中的解构变量没有正确键入(如果将它们悬停,您会看到它们都是 number | React.MutableRefObject&lt;HTMLCanvasElement&gt; 类型)。

你需要的是使用一个元组来告诉 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]
}

【讨论】:

    猜你喜欢
    • 2020-12-21
    • 1970-01-01
    • 2021-06-18
    • 2021-03-01
    • 2021-04-14
    • 1970-01-01
    • 2022-10-21
    • 2016-08-23
    • 2019-03-18
    相关资源
    最近更新 更多