【问题标题】:Property 'current' does not exist on type '((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement>'类型 '((instance: HTMLDivElement | null) => void) | 上不存在属性 'current' RefObject<HTMLDivElement>'
【发布时间】:2021-01-24 22:43:13
【问题描述】:

通常当我使用 React + Typescript 并且我必须使用 refs 时,我通常会使用此检查:

const ref = useRef<HTMLDivElement>(null)
...
if(ref && ref.current)

但是最近,我收到了这个错误:

Property 'current' does not exist on type '((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement>'.
  Property 'current' does not exist on type '(instance: HTMLDivElement | null) => void'.ts(2339)

关于这个错误意味着什么的任何想法?为了解决这个问题,作为一种变通方法,我添加了第三个检查:

if(ref && "current" in ref && ref.current)

但这看起来很糟糕,主要是当您必须同时处理多个引用时。

感谢您的帮助。

【问题讨论】:

  • 引用是如何创建的?使用 useRef,您总是会得到一个 ref 对象,这就是您的普通代码可以工作的原因。但看起来这段代码可能会收到一个 ref 回调。
  • 我正在创建这样的引用 const cardRef = useRef&lt;HTMLDivElement&gt;(null);
  • 这不应该产生您所描述的问题。您是否在某处重新定义了类型?比如const ref: Ref&lt;HtmlDivElement&gt; = cardRef?或者将它作为道具传递给需要Ref&lt;HtmlDivElement&gt;的组件?

标签: javascript reactjs typescript


【解决方案1】:

现代 React 中有两种 ref:ref 对象和 ref 回调。 Ref 对象是由useRef(或在类组件中,createRef)创建的:它是一个具有current 属性的对象。在打字稿中,它们的类型为RefObject&lt;T&gt;,其中Tcurrent 上的任何值。

Ref 回调是另一种选择,在某些高级情况下需要它。您将一个函数传递给元素,该函数将在创建或销毁实例时回调。它们的类型为(instance: T) =&gt; void

将 ref 对象和 ref 回调组合为单一类型的简写是 Ref&lt;T&gt;,看起来这就是您的代码所期望的。由于您尚未显示该代码,因此我将不得不对其外观进行一些有根据的猜测。假设您有一个接受 ref 作为 prop 的组件(也许它可以将其交给其内部组件之一):

interface ExampleProps {
  buttonRef: Ref<HTMLButtonElement>
}

const Example: FC<ExampleProps> = ({ buttonRef }) => {
  return (
    <div>
      <button ref={buttonRef}>Hello</button>
    <div>
  )
}

由于我已经将 prop 定义为 Ref,它可以在 ref 对象或 ref 回调中传递。在这种情况下这很好,因为除了将它传递给按钮之外,我没有对它做任何事情。但是如果我尝试编写一些代码与之交互,我不能假设它是一个对象或一个函数。

如果我需要这样做,也许我可以限制 prop 使其只接受 ref 对象,然后我可以假设它将具有.current

interface ExampleProps {
  buttonRef: RefObject<HTMLButtonElement>
}

const Example: FC<ExampleProps> = ({ buttonRef }) => {
  useEffect(() => {
    console.log(buttonRef.current);
  });
  return (
    <div>
      <button ref={buttonRef}>Hello</button>
    <div>
  )
}

但也许我不想限制我的组件的使用方式,但我仍然需要能够以某种方式与 ref 交互。在这种情况下,我可能需要自己创建一个回调 ref,然后向它添加逻辑来处理我对 ref 的使用以及 prop 对 ref 的使用:

interface ExampleProps {
  buttonRef: Ref<HTMLButtonElement>
}

const Example: FC<ExampleProps> = ({ buttonRef }) => {
  const myRef = useRef<HTMLButtonElement>(null);
  useEffect(() => {
    console.log(myRef.current);
  });
  return (
    <div>
      <button ref={(element) => {
        (myRef as MutableRefObject<HTMLButtonElement>).current = element;
        if (typeof buttonRef === 'function') {
          buttonRef(element);
        } else {
          buttonRef.current = element;
        }
      }}>Hello</button>
    <div>
  )
}

需要as MutableRefObject&lt;HTMLButtonElement&gt; 的类型断言,因为myRef 被标记为不可变。这种类型反映了一个事实,即只有 react 应该修改 .current 属性。这对于正常的用例来说是好的,但是由于我们从 react 中接管了这个责任,所以改变值是可以的。

【讨论】:

    猜你喜欢
    • 2022-01-04
    • 2017-08-18
    • 2022-09-23
    • 2020-07-20
    • 2018-02-23
    • 2022-01-26
    • 2020-04-26
    • 2022-12-21
    • 2019-11-30
    相关资源
    最近更新 更多