在 React 自定义钩子中正确输入 useRef 值

时间:2021-06-29 20:45:51

标签: reactjs typescript react-hooks use-ref

我有一个自定义挂钩,可在我的 TS 应用中返回值 useRef。不幸的是,它抱怨我返回的引用类型,我不知道如何正确输入。

这是我的钩子的样子:


interface MyHookInterface {
    someBooleanState: boolean
    myRef: HTMLElement | null
}

  
const useMyHook = (): MyHookInterface => {
    const [someBooleanState, setSomeBooleanState] = useState<boolean>(false)
    const myRef = useRef<HTMLElement | null>(null)
  
    useEffect(() => {
      const el = myRef.current // what type should this be?
      // Complaining that el possibly undefined 
      if(el?.offsetWidth < el?.scrollWidth){
          // do stuff
      }
    }, [])
  
    return {
        someBooleanState,
        myRef, // Getting: Type 'MutableRefObject<HTMLElement | null>' is missing the following properties from type 'HTMLElement': accessKey, accessKeyLabel, autocapitalize, dir, and 234 more
    }
  }
  

正如你在评论中看到的,我的钩子有一些与打字有关的错误:

1- 不知道如何在界面中输入myRef。请记住,它将用于多种类型的 HTML 元素,因此我无法在此处指定它是 div 还是什么。

2- 不知道如何输入 el,但对其属性的访问抱怨它是 undefined

如何在钩子中正确键入这些值?

2 个答案:

答案 0 :(得分:2)

发生这种情况是因为引用的值存储在“.current”属性下。

const Comp = () => {
...
    const refVal = React.useRef(2);
    console.log(2 === refVal); // false
    console.log(2 === refVal.current); // true
...
}

解决方案取决于您的意图 - 如果您想返回 ref 本身,请按照类型错误的建议将接口类型更改为 MutableRefObject<HTMLElement | null>,否则,将返回值替换为:

    return {
        someBooleanState,
        myRef: myRef.current,
    }

如果 el 尚未定义(即尚未分配),由于您使用 undefined 运算符访问该属性,您可能会得到 ?. ,是正确的。

例如

null?.test === undefined; // true

要解决这个问题,请检查是否定义了 el 和可选(尽管接口定义不需要),检查两个值是否都已定义并且是数字(即使用 el && !isNaN(el?.offsetWidth) && !isNaN(el?.scrollWidth) && el.offsetWidth < el.scrollWidth。或者,使用空合并运算符,如果这适用于您的用例,即 (el?.offsetWidth ?? 0) < (el?.scrollWidth ?? 0)

答案 1 :(得分:2)

ref 的类型不仅仅是它所引用的对象。它是一个 React.MutableRefObject 包装它所引用的内容。这就是提供 current 属性以便 ref 可以工作的原因。

如果您仔细考虑 myRef,您应该会看到您需要的类型。在这种情况下:

React.MutableRefObject<HTMLElement | null>

这让你的钩子返回类型:

interface MyHookInterface {
    someBooleanState: boolean
    myRef: React.MutableRefObject<HTMLElement | null>
}

其次,这不起作用的原因:

  const el = myRef.current // what type should this be?
  
  // Complaining that el possibly undefined 
  if(el?.offsetWidth < el?.scrollWidth){
      // do stuff
  }

是因为您的 ref 可能尚未分配值。这意味着 el?.offsetWidthundefined,因为 el 仍然是 null。并且 undefined 不是 < 比较中的有效操作数。 (if (undefined < undefined) 没有多大意义)

您可以通过在进行比较之前检查以确保 el 存在来轻松解决此问题:

  if (el && el.offsetWidth < el.scrollWidth){
      // do stuff
  }

Working example