如何在Flow中为useRef Hook添加类型标注?
Got it, let's fix your Flow type annotation issue with useRef—this is a common gotcha when switching between Flow and TypeScript. The error you're seeing happens because Flow infers inputRef.current as null by default (since you didn't provide a type or initial value), and null doesn't have a focus() method.
Here's the Correct Flow Syntax for Your Case
In Flow, you need to explicitly specify the ref's type via a generic and initialize it with null (since the ref will be null until the component mounts). Here's how to adjust your code:
// @flow import * as React from 'react'; import { useRef, useState } from "react"; import type { ComponentType } from "react"; const App: ComponentType<{}> = () => { const [email, setEmail] = useState(""); // Add type annotation for the change event to keep Flow happy const handleChange = (e: React.ChangeEvent<HTMLInputElement>): void => { e.preventDefault(); setEmail(e.target.value); }; // Annotate useRef with the HTML element type and initialize to null const inputRef = useRef<HTMLInputElement>(null); return ( <> <input ref={inputRef} name="email" value={email} onChange={handleChange} /> <button onClick={() => { // Use optional chaining to safely call focus() (handles the null case) inputRef.current?.focus(); // Alternatively, if you're certain the ref is set (like on button click post-mount), // you can use a type assertion to tell Flow current isn't null: // (inputRef.current: HTMLInputElement).focus(); }}>Ref</button> </> ); }; export default App;
Key Differences from TypeScript
- Initial Value Requirement: Unlike TypeScript, Flow requires you to pass an initial value to
useRefwhen using a generic type. Since the ref starts asnullbefore the input mounts, we passnullhere to match the expected type. - Type Inference: Flow infers the
currentproperty type from the combination of the generic and initial value. SouseRef<HTMLInputElement>(null)gives us a ref withcurrent: HTMLInputElement | null.
Why Your Original Code Failed
When you wrote const inputRef = useRef(); without any type or initial value, Flow inferred inputRef.current as void (or null in some contexts), which doesn't have the focus() method. By adding the generic type and initial null value, we tell Flow exactly what type of element the ref will hold once the component mounts.
Bonus: Safe Access to the Ref
Using ?. (optional chaining) is the safest way to call methods on the ref, as it gracefully handles edge cases where current might still be null. In your button click scenario, the input will have mounted by the time the button is clicked, so the type assertion is also valid if you prefer that syntax.
内容的提问来源于stack exchange,提问作者Noob

