【问题标题】:Typing a custom useRef hook for any type of HTML element为任何类型的 HTML 元素键入自定义 useRef 挂钩
【发布时间】:2021-04-27 10:16:29
【问题描述】:

我对 Typescript 还是有点陌生​​,我的目标是在 Typescript 中创建一个自定义的 React.useRef 钩子,它返回一个引用。我希望为任何 HTML 元素输入此引用,而不仅仅是按钮。我遇到了正确键入此自定义挂钩的问题。

这是我的钩子:

type CustomRefHook = (dependencies?: string | boolean | number[]) => React.MutableRefObject<HTMLButtonElement | null>;

const useCustomRefHook: CustomRefHook = (...dependencies) => {
  const ref = React.useRef<HTMLButtonElement | null>(null);

  useEffect(() => {
    // ... do stuff
  }, dependencies)

  return ref;
}

目前,这个钩子的大部分用例都是用于按钮,但我希​​望最终将它扩展到任何类型的 HTML 元素。我试过使用 HTMLElement 而不是 HTMLButtonElement ,但是我得到一个类型错误:

Type 'MutableRefObject<HTMLElement | null>' is not assignable to type 'string | ((instance: HTMLButtonElement | null) => void) | RefObject<HTMLButtonElement> | null | undefined'.
  Type 'MutableRefObject<HTMLElement | null>' is not assignable to type 'RefObject<HTMLButtonElement>'.
    Types of property 'current' are incompatible.
      Type 'HTMLElement | null' is not assignable to type 'HTMLButtonElement | null'.

每当我尝试将此引用附加到按钮时。使用 HTMLButtonElement 可以消除 Typescript 错误,但我希望这个钩子能够处理任何类型的 HTML 元素。

【问题讨论】:

  • 您需要为元素类型使用泛型。
  • 那会是什么样子?我试过类似:type CustomRefHook = &lt;T&gt;(dependencies?: string | boolean | number[]) =&gt; React.MutableRefObject&lt;T&gt;;
  • 是的,基本上就是这样。我会输入一个答案。

标签: html reactjs typescript ref


【解决方案1】:

ref 的类型需要与它所附加的 DOM 元素完全匹配,因此需要使用泛型来指定元素类型。

由于 useCustomRefHook 现在是一个泛型函数,因此将类型声明为内联而不是单独的类型 CustomRefHook 更有意义。

我已经允许这个钩子接受Tany 值,但是如果你只想将它应用于HTML 元素,你可以使用T extends HTMLElement。这可能很重要,具体取决于useEffect 中“做事”的内容。如果“做事”需要任何关于 T 的特定内容,那么您需要确保 T 扩展了具有所需属性/方法的内容。

import React, { MutableRefObject, DependencyList, useEffect, useRef } from "react";

const useCustomRefHook = <T extends any>( dependencies: DependencyList = [] ): MutableRefObject<T | null> => {

  const ref = useRef<T | null>(null);

  useEffect(() => {
    // ... do stuff
  }, dependencies);

  return ref;
};

钩子返回一个基于通用TMutableRefObject&lt;T | null&gt;T 的值不可能从参数中推断出来,因此每次调用它时都需要指定泛型。

const Test = () => {
  const ref = useCustomRefHook<HTMLButtonElement>();

  return <button ref={ref} />;
};

【讨论】:

  • 问:如何将其提取到类型声明中? type CustomRefType = &lt;T extends HTMLElement&gt;(dependencies: React.DependencyList) =&gt; React.MutableRefObject&lt;T | null&gt; const useCustomRefHook: CustomRefType = (dependencies = []) =&gt; { const ref = useRef&lt;T | null&gt;(null); } 我收到一条错误消息 "Cannot find name 'T'"。我如何将泛型类型提供给React.useRef? @Linda Paiste
  • 当函数本身是泛型时,你无法真正提取出来。
  • 知道了。好的,这是有道理的
猜你喜欢
  • 2020-07-26
  • 1970-01-01
  • 2022-11-01
  • 1970-01-01
  • 2018-02-11
  • 2019-11-27
  • 2014-09-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多