reactjs - React onclick Argument av typen 'EventTarget' kan ikke tildeles til parameter av typen 'Node'
Jeg importerer MouseEvent fra react
import { MouseEvent } from 'react';
Bruk MouseEvent i følgende
const closeSelectBox = (e: MouseEvent): void => {
if (!searchOptionWrapRef.current?.contains(e.target)) {
setOpenSelectBox(false)
}
};
Jeg lytter til min closeSelectBox
useEffect(() => {
document.addEventListener("click", closeSelectBox);
return () => {
document.removeEventListener("click", closeSelectBox);
};
}, [])
searchOptionWrapRef er en div
const searchOptionWrapRef = useRef<HTMLDivElement>(null);
<div ref={searchOptionWrapRef}/>
Men jeg får følgende feil
Argument of type 'EventTarget' is not assignable to parameter of type 'Node'.
Type 'EventTarget' is missing the following properties from type 'Node': baseURI, childNodes, firstChild, isConnected, and 43 more.
Hvordan løser jeg denne typefeilen uten å bruke any i stedet for MouseEvent?
Svar #1
Hendelsesgrensesnittene som eksporteres av React er for React-hendelsesbehandlerprops, ikke addEventListener-behandlere. For disse, ikke importer MouseEvent fra React, så får du i stedet DOM globalt grensesnitt for det, som fungerer med addEventListener. Og ja, det er forvirrende. :-)
Men det andre problemet (som faktisk kan være ditt hovedproblem) er at DOM-globalen MouseEvent definerer target som en EventTarget, ikke som en Node. I ditt tilfelle vil det alltid være en Node (spesifikt, en Element), men slik er DOM-typen definert. For å håndtere det har du minst to valg:
Purist
Du kan gå veldig puristisk (det gjør jeg) og bruke en typepåstand-funksjon for å påstå at target er en Node:
// In a utility library:
function assertIsNode(e: EventTarget | null): asserts e is Node {
if (!e || !("nodeType" in e)) {
throw new Error(`Node expected`);
}
}
// And then in your component:
const closeSelectBox = ({target}: MouseEvent): void => {
assertIsNode(target);
if (!searchOptionWrapRef.current?.contains(target)) {
setOpenSelectBox(false);
}
};
Lekerom lenke
Konsis og pragmatisk
Du vet at target er en Node og ikke er null, så du kan bruke en typepåstand (target as Node):
const closeSelectBox = ({target}: MouseEvent): void => {
if (!searchOptionWrapRef.current?.contains(target as Node)) {
setOpenSelectBox(false);
}
};
Lekeromlenke
Jeg liker ikke typepåstander som ikke sjekkes under kjøring (som er hva en typepåstandsfunksjon som assertIsNode gjør), så jeg vil sannsynligvis gå for den første tilnærmingen. Men i begrensede situasjoner der du er sikker på det, kan du vurdere en.
Svar #2
Du kan påstå at instansen er av Element eller HTMLElement ved å bruke instanceof. Denne løsningen løser både kjøretid- og kompileringstid-sjekking på en minimal måte uten å forårsake unntak.
const closeSelectBox = (e: MouseEvent): void => {
if (e.target instanceof HTMLElement && !searchOptionWrapRef.current?.contains(e.target)) {
setOpenSelectBox(false)
}
};
