繁体   English   中英

使用 TypeScript 注释自定义 React Hook

[英]Annotating Custom React Hook With TypeScript

我有一个自定义的 React Hook,可以监视特定元素之外的点击。 它工作得很好,但我在一些地方无法让 TypeScript 满意。

应用程序.js

import { useRef, useCallback } from "react";
import useClick from "./useClick";

export default function App() {
  const asideRef = useRef(null);

  const handleStuff = useCallback(() => {
    console.log("a click outside of the sidebar occurred.");
  }, []);

  useClick(asideRef, handleStuff);

  return (
    <div className="App">
      <aside ref={asideRef}>
        <nav>
          <ul></ul>
        </nav>
      </aside>
    </div>
  );
}

使用Click.js

import React, { useEffect } from "react";

const useClick = (ref: React.MutableRefObject<HTMLElement>, cb: () => void) => {
  useEffect(() => {
    const checkClick = (e: React.MouseEvent): void => {
      if (ref.current && !ref.current.contains(e.target as Node)) {
        cb();
      }
    };

    document.addEventListener("click", checkClick);

    return () => {
      document.removeEventListener("click", checkClick);
    };
  }, [ref, cb]);
};

export default useClick;

第一个问题区域是在App.js ,这里调用了useClick钩子。 TypeScript 抱怨传递给useClick的第一个参数并给出以下消息:

Argument of type 'MutableRefObject<null>' is not assignable to parameter of type 'MutableRefObject<HTMLElement>'.
  Type 'null' is not assignable to type 'HTMLElement'.ts(2345)

我知道这与我将 ref 的初始值设置为 null 有关,并且useClick中的 ref 参数被注释为React.MutableRefObject<HTMLElement> 我只是不知道如何解决它。

第二个问题区域是在useClick.js ,其中添加和删除了事件侦听器。 TypeScript 似乎对我的checkClick函数有问题。 错误太长了,我别无选择,只能在下面展示它的照片。

如果有人对如何解决这两个问题有任何想法,那么 TypeScript 会很高兴,我们将不胜感激。

在此处输入图片说明

Hi Dan:我将从需要改变的地方开始,然后在下面解释原因。 (我还重命名了您的 TypeScript 文件扩展名以反映它们的内容。)

useClick.ts

前:

// ...
const useClick = (ref: React.MutableRefObject<HTMLElement>, cb: () => void) => {
  useEffect(() => {
    const checkClick = (e: React.MouseEvent): void => {
// ...

后:

// ...
const useClick = (ref: React.RefObject<HTMLElement>, cb: () => void) => {
  useEffect(() => {
    const checkClick = (e: MouseEvent): void => {
// ...

App.tsx

前:

export default function App() {
  const asideRef = useRef(null);

后:

export default function App() {
  const asideRef = useRef<HTMLElement>(null);

首先,让我们解决checkClick函数:这个函数签名应该可以分配给lib.dom.d.tsEventListener类型:

interface EventListener {
    (evt: Event): void;
}

因为你的参数是React.MouseEvent ,它没有扩展原生的Event类型,所以不兼容。 只需使用本机MouseEvent类型,因为您正在将侦听器添加到文档(无论如何与 React 无关。)

接下来,让我们看看useClick的函数签名:

在阅读本部分时,您可能希望参考useRef的类型定义:

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/5149827c1f97541dd69d950039b83ace68e119e6/types/react/index.d.ts#L1025-L1063

第一个参数是唯一需要更改的参数,它需要从MutableRefObject更改为RefObject 它们之间的区别可能很微妙,但您可以阅读一些很棒的资源来了解更多关于它们的信息。 例如,这里有一个:

https://dev.to/wojciechmatuszewski/mutable-and-immutable-useref-semantics-with-react-typescript-30c9

在创建传递给 React 以用于元素引用的 ref 时,您应该提供null作为useRef (您所做的)的初始参数,并为其应保存的值类型提供泛型类型注释(在本例中)它是HTMLElement )。 当为 DOM 元素使用 ref 时,React 希望你永远不会改变这个 ref,因为它是由 React 控制的,所以在这种情况下useRef返回的类型只是一个RefObject 因此,这就是您应该用于useClick的第一个参数的useClick

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM