打字稿自定义钩子,事件类型问题

时间:2021-07-03 12:09:54

标签: reactjs typescript

大家好,我有两个问题

App.tsx

const App = () => {
  const [data, getData] = useGetData('posts');
  const [show, handleModal] = useHandleModal();

  useEffect(() => {
    console.log(show);
  }, [show]);

  return (
    <div>
      <input type="button" name="name" value="button" onClick={getData} />
      <input type="button" name="name2" value="button2" onClick={handleModal} />
    </div>
  );
};

错误代码

<input type="button" name="name2" value="button2" onClick={handleModal} />

错误信息

Type 'boolean | ((e: any) => void)' is not assignable to type 'MouseEventHandler<HTMLInputElement> | undefined'.
  Type 'false' is not assignable to type 'MouseEventHandler<HTMLInputElement> | undefined'.ts(2322)

为什么 onClick 是错误的?

我不明白这个错误信息

可能是自定义钩子函数类型问题

但是我不知道在哪里声明类型

useHandleModal.tsx(自定义钩子)

import React, { useState, useCallback } from 'react';

export default () => {
  const [show, setShow] = useState<boolean>(false);

  const handleModal = useCallback(
    (e: any) => {
      setShow(!show);
    },
    [show],
  );

  return [show, handleModal];
};

我想在自定义钩子中使用事件

我可以声明任何但我不使用任何

请告诉我活动类型

2 个答案:

答案 0 :(得分:2)

发生这种情况是因为您将钩子中的变量作为数组返回。当您这样做时,打字稿会推断数组类型,在您的情况下为 boolean | ((e: any) => void)[],因此数组中的每个条目的类型为 boolean | ((e: any) => void),这当然与 {{1} 不兼容}

您可以采取一些措施来解决打字问题

  1. 首先你可以使用一个对象返回它(并将它作为对象解构获取)

    MouseEventHandler<HTMLInputElement>

    在这种情况下,typescript 能够单独推断对象的每个值,而不是整体推断。

  2. 您可以做的第二件事是在导出数组时明确告诉打字稿将数组中的每个条目视为常量(// in hook return {show, handleModal}; // in app const {show, handleModal} = useHandleModal(); ,精确类型)。并且您以同样的方式获得它。

    readonly

在钩子内输入事件

如果您想使用钩子内的事件,您可以使用以下输入 return [show, handleModal] as const; 并且您还应该使用 (e: React.MouseEvent<HTMLInputElement>) 而不是 currentTarget。我不会详细介绍这是什么,但我会给你一些参考:

MDN Docs on currentTarget

根据你在这篇文章上留下的评论,我想给你一个示例片段:

target

答案 1 :(得分:0)

您可以查看有关 useStates 类型的示例。最重要的是 onClick、onChange 和 onSubmit 的示例

export interface ValidUser {
  user: UserReducedInfo,
  userFullData : User | null | undefined
}

export default function useUser (): ValidUser | null | undefined {
  const [user, setuser] = useState<UserReducedInfo | null | undefined>(null)
  const [userFullData, setuserFullData] = useState<User | null |undefined>(null)

  // more code

  return { user, userFullData }
}

 const handleClick : MouseEventHandler = () :void => {
    // Your code
  }

const handleChange: React.ChangeEventHandler = (
    e: React.ChangeEvent<HTMLTextAreaElement>
  ): void => {
    // your code
  }

const handleSubmit: 
React.FormEventHandler<HTMLFormElement> = (
    e: React.FormEvent<HTMLFormElement>
  ): void => {
    e.preventDefault()
// your code
}