typescript - Under hvilke betingelser er AbortSignal i TanStack useQuery-funktionen udefineret?
Dokumentationen for TanStack React Query (https://tanstack.com/query/v4/docs/react/guides/query-cancellation) forklarer, hvordan queryFn-egenskaben kan modtage et objekt med en signal-egenskab, som kan bruges til at annullere en forespørgsel, som i dette eksempel.
const query = useQuery({
queryKey: ['todos'],
queryFn: async ({ signal }) => {
const todosResponse = await fetch('/todos', {
signal,
})
const todos = await todosResponse.json()
const todoDetails = todos.map(async ({ details }) => {
const response = await fetch(details, {
signal,
})
return response.json()
})
return Promise.all(todoDetails)
},
})
Problemet er, at med TypeScript er denne signalegenskab typet som AbortSignal | undefined. Med det API, jeg bruger, tilføjer det en hel del kompleksitet til koden, hvis man skal tjekke betinget, om signal er sat, så det ville være meget hjælpsomt at vide, under hvilke betingelser dette signal-objekt ikke er defineret. Enhver idé vil være meget værdsat.
Svar #1
react-query v4.29.11
signal vil eksistere, hvis AbortController-klassen eksisterer. Lad os tage et kig på kildekoden:
signal-egenskaben tilføjes til forespørgselsfunktionskonteksten af addSignalProperty()-funktionen, se nedenfor:
const addSignalProperty = (object: unknown) => {
Object.defineProperty(object, 'signal', {
enumerable: true,
get: () => {
if (abortController) {
this.abortSignalConsumed = true
return abortController.signal
}
return undefined
},
})
}
addSignalProperty(queryFnContext)
abortController fås ved getAbortController()-funktionen
export function getAbortController(): AbortController | undefined {
if (typeof AbortController === 'function') {
return new AbortController()
}
return
}
Derfor er TS-typen for signal-egenskaben: AbortSignal | undefined.
Den officielle dokumentation nævner det også.
API'en
AbortControllerer tilgængelig i de fleste runtime-miljøer, men hvis runtime-miljøet ikke understøtter den, vil forespørgselsfunktionen modtageundefinedi stedet. Du kan vælge at polyfilleAbortController-API'en, hvis du ønsker det; der er flere tilgængelige.
Svar #2
Ok, så i mit tilfælde gjorde jeg bare dette, det virkede
const getUserData = async ({
queryKey,
signal,
}: QueryFunctionContext<[string, Person]>): Promise<User> => {
const [, selectedUser] = queryKey;
const response = await axios.get(`/api/person?person=${selectedUser}`, {
signal,
});
return response.data;
};
const { data, error, isLoading } = useQuery({
queryKey: ["users", selectedUser as Person],
queryFn: getUserData,
enabled: !!selectedUser,
});
