简体   繁体   English

如何在 Flow 中输入 useRef 挂钩?

[英]How to type useRef hook in Flow?

I can't figure out how to type a useRef hook in Flow.我不知道如何在 Flow 中键入useRef挂钩。 In TS I could just do:在 TS 中,我可以这样做:

const inputRef = useRef<InputRefType>();

But this doesn't work in Flow and I'm unsure what to replace it with.但这在 Flow 中不起作用,我不确定用什么替换它。

This is what the code looks like:这是代码的样子:

const inputRef = useRef();
return (
  <>
    <input ref={inputRef} name="email" value={email} onChange={handleChange} />
    <button onClick={() => inputRef.current.focus()}>Ref</button>
  </>
);

Here is the error message:这是错误消息:

Cannot call inputRef.current.focus because property focus is missing in null [1]. [incompatible-use]

     src/App.js
      30│       }}
      31│     />
      32│     <input ref={inputRef} name="email" value={email} onChange={handleChange} />
      33│     <button onClick={() => inputRef.current.focus()}>Ref</button>
      34│   </>
      35│ );
      36│ };

     /private/tmp/flow/flowlib_1fa18dde633e97c7_501/react.js
 [1] 197│   | { -current: React$ElementRef<ElementType> | null, ... }

Complete App.js file:完整的 App.js 文件:

// @flow
import * as React from 'react';
import { useRef, useState } from "react";
import type { ComponentType } from "react";

const App: ComponentType<{}>  = () => {
  const [email, setEmail] = useState("");

  const handleChange = (e): void => {
    e.preventDefault();
    setEmail(e.target.value);
  }

  const inputRef = useRef();

return (
  <>
    <input ref={inputRef} name="email" value={email} onChange={handleChange} />
    <button onClick={() => inputRef.current.focus()}>Ref</button>
  </>
);
};

export default App;

Error:错误: 错误图片

You can solve this in a number of ways, either you declare the ref as it's type like so您可以通过多种方式解决此问题,或者将 ref 声明为它的类型,如下所示

const inputRef = useRef<HTMLInputElement | null>(null);

Because inputRef is initially null when you initialise it, so just HTMLInputRef would be incorrect.因为inputRef在初始化时最初是 null ,所以只是HTMLInputRef是不正确的。 This is a native JS class that can just be used, it's not a flow type.这是一个可以使用的原生JS class,它不是流类型。


A simpler way is to ignore the declaration and write inputRef.current?.focus() as mentioned in the comments and this works fine for this example but is limited by inference because you're never checking or defining the type.一种更简单的方法是忽略声明并编写注释中提到的inputRef.current?.focus() ,这对于本示例来说效果很好,但受到推理的限制,因为您从不检查或定义类型。


Or the other way is through type refinement where instead of just doing a null check you also check for whether it's the type you expect.或者另一种方法是通过类型细化,而不是仅仅进行 null 检查,您还检查它是否是您期望的类型。

if (inputRef.current instanceof HTMLInputElement) {
  inputRef.current.focus();
}

This protects you against soundness errors in case in the off chance inputRef.current is defined but it ends up being a button instead of an input element.这可以保护您免受稳健性错误的影响,以防万一inputRef.current被定义但它最终成为一个按钮而不是一个输入元素。


The choice is really up to you and depends on your needs.选择实际上取决于您,并取决于您的需求。 They'll all work for your use case.它们都适用于您的用例。

You should do a null check before calling inputRef.current?.focus()您应该在调用inputRef.current?.focus()之前进行 null 检查

// @flow
import * as React from 'react';
import { useRef, useState } from "react";
import type { ComponentType } from "react";

const App: ComponentType<{}> = () => {
    const [email, setEmail] = useState("");

    const handleChange = (e): void => {
        e.preventDefault();
        setEmail(e.target.value);
    }

    const inputRef = useRef();

    return (
        <>
            <input ref={inputRef} name="email" value={email} onChange={handleChange} />
            <button onClick={() => inputRef.current?.focus()}>Ref</button>
        </>
    );
};

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

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