reactjs - Hur skriver jag en ref som används på godtyckliga element med React och TypeScript?
Jag har en React Hook som kan användas på godtyckliga element (allt som utökar HTMLElement) för att upptäcka om elementet är hovrat över. När jag försöker skriva typanvändningen kan jag inte tillfredsställa TypeScript-kompilatorn. Här är en enkel reproduktion:
function useHover<T extends HTMLElement>(): [MutableRefObject<T>] {
const ref = useRef<T | null>(null);
return [ref];
}
const App = () => {
const [ref] = useHover<HTMLButtonElement | HTMLAnchorElement>();
const Element = Math.random() > 0.5 ? 'a' : 'button';
return <Element ref={ref}>{`tag: ${Element}`}</Element>;
};
Inom Hooken vet jag inte vilken elementtyp som kommer att användas, så jag använder en generisk typ med extends HTMLElement-begränsning. Inom React-komponenten vet jag däremot den begränsade uppsättningen av elementtyper som ref:en kommer att användas med.
Med koden ovan får jag detta typfel:
Type 'MutableRefObject<HTMLButtonElement | HTMLAnchorElement>' is not assignable to type 'LegacyRef<HTMLAnchorElement> & LegacyRef<HTMLButtonElement>'.
Type 'MutableRefObject<HTMLButtonElement | HTMLAnchorElement>' is not assignable to type 'RefObject<HTMLAnchorElement> & RefObject<HTMLButtonElement>'.
Type 'MutableRefObject<HTMLButtonElement | HTMLAnchorElement>' is not assignable to type 'RefObject<HTMLAnchorElement>'.
Types of property 'current' are incompatible.
Type 'HTMLButtonElement | HTMLAnchorElement' is not assignable to type 'HTMLAnchorElement'.
Type 'HTMLButtonElement' is missing the following properties from type 'HTMLAnchorElement': charset, coords, download, hreflang, and 19 more.
Vilket skulle vara det korrekta sättet att skriva denna Hook och komponent så att jag kan använda Hooken på vilken element som helst som utökar HTMLElement?
Svar #1
Det korrekta sättet att skriva ref som
- innehåller ett element (
T extends HTMLElement) och - kommer att kontrolleras av React (du avser att skicka det till
ref-egenskapen för JSX-elementet)
är RefObject<T>. Referera till typdeklarationsfilen som definierar useRef:
function useRef<T>(initialValue: T|null): RefObject<T>;
Så här kan du skriva en hook som returnerar en ref på det sättet:
TS Lekplats
import {type RefObject, useRef} from 'react';
function useElementRef <T extends HTMLElement>(): RefObject<T> {
const ref = useRef<T>(null);
return ref;
}
Du behöver dock inte använda en ref för en "useHover"-hook (som avgör om ett element är hovrat av en pekare eller inte). Se mitt andra svar för det.
