0
点赞
收藏
分享

微信扫一扫

关于 useRef 返回值的类型声明探究

芒果六斤半 2022-02-17 阅读 287

现上段代码:

import { useRef } from "react";

const Main = () => {
  // useRef 没有传入参数,也就是传入了 undefined
  // 查看 divRef 的类型。
  // const divRef: React.MutableRefObject<HTMLDivElement | undefined>
  const divRef = useRef<HTMLDivElement>();
  return (
    <div>
      // 查看 div 的 ref 属性的类型
      // React.LegacyRef<HTMLDivElement> | undefined
      <div ref={divRef}>useRef and null</div>
    </div>
  );
};

export default Main;

在 vscode 可以看到代码是有报错的:
在这里插入图片描述
不能将类型React.MutableRefObject<HTMLDivElement | undefined>分配给类型React.LegacyRef<HTMLDivElement> | undefined
最终不兼容的是 current:不能将类型HTMLDivElement | undefined分配给类型HTMLDivElement | null

后面再分析原因,先看解决方法

接着在 useRef 传入 null:

import { useRef } from "react";

const Main = () => {
  // const divRef: React.RefObject<HTMLDivElement>
  const divRef = useRef<HTMLDivElement>(null);
  return (
    <div>
      // React.LegacyRef<HTMLDivElement> | undefined
      <div ref={divRef}>useRef and null</div>
    </div>
  );
};

export default Main;

可以看到报错没有了。

其实 useRef 传不传入null,都可以正常运行(可以在 js 里测试),错误是 ts 报的类型问题。

报错原因分析,查看 useRef ts 声明文件,看到如下定义:

    interface RefObject<T> {
        readonly current: T | null;
    }

    interface MutableRefObject<T> {
        current: T;
    }

    function useRef<T>(initialValue: T|null): RefObject<T>;

    function useRef<T = undefined>(): MutableRefObject<T | undefined>;

找到了 useRef 的两份声明,根据是否有传入参数,决定了返回值的类型。

查看 ref 属性声明


    interface RefObject<T> {
        readonly current: T | null;
    }
    type RefCallback<T> = { bivarianceHack(instance: T | null): void }["bivarianceHack"];
    type Ref<T> = RefCallback<T> | RefObject<T> | null;
    type LegacyRef<T> = string | Ref<T>;

    interface ClassAttributes<T> extends Attributes {
        ref?: LegacyRef<T>;
    }
  • 所以不传入 null 时,useRef 返回值的类型为MutableRefObject<T | undefined>,current 的类型为T | undefined
    • 注意MutableRefObject<T | undefined>中,T | undefined整体传入interface MutableRefObject<T>,所以interface MutableRefObject<T>中T的类型为T | undefined,所以 current 的类型为T | undefined
  • 而 ref 属性想要的类型为RefObject<T>,current 的类型为T | null
  • T | undefinedT | null 类型不兼容
举报

相关推荐

0 条评论