Framework
Version

Migration zu React Query 3

Frühere Versionen von React Query waren großartig und brachten einige erstaunliche neue Features, mehr Magie und ein insgesamt besseres Erlebnis für die Bibliothek. Sie brachten auch massive Adoption und damit viele verfeinernde Einflüsse (Probleme/Beiträge) für die Bibliothek und brachten einige Dinge ans Licht, die mehr Politur brauchten, um die Bibliothek noch besser zu machen. v3 enthält genau diese Politur.

Übersicht

  • Skalierbarere und testbarere Cache-Konfiguration
  • Bessere SSR-Unterstützung
  • Data-Lag (früher usePaginatedQuery) überall!
  • Bidirektionale Infinite Queries
  • Query-Datenselektoren!
  • Konfigurieren Sie Standardwerte für Queries und/oder Mutationen vollständig vor der Verwendung.
  • Mehr Granularität für optionale Rendering-Optimierung
  • Neuer useQueries Hook! (Variable parallele Query-Ausführung)
  • Query-Filterunterstützung für den useIsFetching() Hook!
  • Retry-/Offline-/Replay-Unterstützung für Mutationen
  • Queries/Mutationen außerhalb von React beobachten
  • Verwenden Sie die Kernlogik von React Query, wo immer Sie wollen!
  • Gebündelte/kollokierte Devtools über react-query/devtools
  • Cache-Persistenz zu Web Storage (experimentell über react-query/persistQueryClient-experimental und react-query/createWebStoragePersistor-experimental)

Breaking Changes

Die QueryCache wurde in eine QueryClient und niedrigere Instanzen von QueryCache und MutationCache aufgeteilt.

Die QueryCache enthält alle Queries, die MutationCache enthält alle Mutationen, und die QueryClient kann verwendet werden, um Konfigurationen festzulegen und mit ihnen zu interagieren.

Dies hat einige Vorteile

  • Ermöglicht unterschiedliche Arten von Caches.
  • Mehrere Clients mit unterschiedlichen Konfigurationen können denselben Cache verwenden.
  • Clients können verwendet werden, um Queries zu verfolgen, was für gemeinsam genutzte Caches bei SSR verwendet werden kann.
  • Die Client-API ist stärker auf allgemeine Nutzung ausgerichtet.
  • Einfacher zu testende Einzelkomponenten.

Beim Erstellen eines new QueryClient() werden automatisch eine QueryCache und eine MutationCache für Sie erstellt, wenn Sie keine angeben.

tsx
import { QueryClient } from 'react-query'

const queryClient = new QueryClient()
import { QueryClient } from 'react-query'

const queryClient = new QueryClient()

ReactQueryConfigProvider und ReactQueryCacheProvider wurden beide durch QueryClientProvider ersetzt.

Standardoptionen für Queries und Mutationen können jetzt in QueryClient angegeben werden.

Beachten Sie, dass es sich jetzt um defaultOptions anstelle von defaultConfig handelt.

tsx
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      // query options
    },
    mutations: {
      // mutation options
    },
  },
})
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      // query options
    },
    mutations: {
      // mutation options
    },
  },
})

Die Komponente QueryClientProvider wird nun verwendet, um einen QueryClient mit Ihrer Anwendung zu verbinden.

tsx
import { QueryClient, QueryClientProvider } from 'react-query'

const queryClient = new QueryClient()

function App() {
  return <QueryClientProvider client={queryClient}>...</QueryClientProvider>
}
import { QueryClient, QueryClientProvider } from 'react-query'

const queryClient = new QueryClient()

function App() {
  return <QueryClientProvider client={queryClient}>...</QueryClientProvider>
}

Die Standard-QueryCache ist weg. Diesmal wirklich!

Wie bereits mit einer Deprecation angemerkt, gibt es keine Standard-QueryCache mehr, die aus dem Hauptpaket erstellt oder exportiert wird. Sie müssen Ihre eigene über new QueryClient() oder new QueryCache() (die Sie dann an new QueryClient({ queryCache }) übergeben können) erstellen.

Das veraltete Hilfsprogramm makeQueryCache wurde entfernt.

Es hat lange gedauert, aber jetzt ist es endlich weg :)

QueryCache.prefetchQuery() wurde zu QueryClient.prefetchQuery() verschoben.

Die neue Funktion QueryClient.prefetchQuery() ist asynchron, gibt aber nicht die Daten aus der Query zurück. Wenn Sie die Daten benötigen, verwenden Sie die neue Funktion QueryClient.fetchQuery().

tsx
// Prefetch a query:
await queryClient.prefetchQuery('posts', fetchPosts)

// Fetch a query:
try {
  const data = await queryClient.fetchQuery('posts', fetchPosts)
} catch (error) {
  // Error handling
}
// Prefetch a query:
await queryClient.prefetchQuery('posts', fetchPosts)

// Fetch a query:
try {
  const data = await queryClient.fetchQuery('posts', fetchPosts)
} catch (error) {
  // Error handling
}

ReactQueryErrorResetBoundary und QueryCache.resetErrorBoundaries() wurden durch QueryErrorResetBoundary und useQueryErrorResetBoundary() ersetzt.

Zusammen bieten diese die gleiche Erfahrung wie zuvor, jedoch mit zusätzlicher Kontrolle, um auszuwählen, welche Komponentenbäume zurückgesetzt werden sollen. Weitere Informationen finden Sie unter

QueryCache.getQuery() wurde durch QueryCache.find() ersetzt.

QueryCache.find() sollte nun verwendet werden, um einzelne Queries aus einem Cache nachzuschlagen.

QueryCache.getQueries() wurde zu QueryCache.findAll() verschoben.

QueryCache.findAll() sollte nun verwendet werden, um mehrere Queries aus einem Cache nachzuschlagen.

QueryCache.isFetching wurde zu QueryClient.isFetching() verschoben.

Beachten Sie, dass es sich jetzt um eine Funktion anstelle einer Eigenschaft handelt.

Der Hook useQueryCache wurde durch den Hook useQueryClient ersetzt.

Er gibt den bereitgestellten queryClient für seinen Komponententeilbaum zurück und sollte nicht viel mehr als eine Umbenennung erfordern.

Teile von Query-Schlüsseln werden nicht mehr automatisch an die Query-Funktion übergeben.

Inline-Funktionen sind jetzt der empfohlene Weg, um Parameter an Ihre Query-Funktionen zu übergeben.

tsx
// Old
useQuery(['post', id], (_key, id) => fetchPost(id))

// New
useQuery(['post', id], () => fetchPost(id))
// Old
useQuery(['post', id], (_key, id) => fetchPost(id))

// New
useQuery(['post', id], () => fetchPost(id))

Wenn Sie immer noch darauf bestehen, keine Inline-Funktionen zu verwenden, können Sie die neu übergebene QueryFunctionContext verwenden.

tsx
useQuery(['post', id], (context) => fetchPost(context.queryKey[1]))
useQuery(['post', id], (context) => fetchPost(context.queryKey[1]))

Infinite Query Page-Parameter werden jetzt über QueryFunctionContext.pageParam übergeben.

Sie wurden zuvor als letzter Query-Key-Parameter in Ihrer Query-Funktion hinzugefügt, aber dies erwies sich für einige Muster als schwierig.

tsx
// Old
useInfiniteQuery(['posts'], (_key, pageParam = 0) => fetchPosts(pageParam))

// New
useInfiniteQuery(['posts'], ({ pageParam = 0 }) => fetchPosts(pageParam))
// Old
useInfiniteQuery(['posts'], (_key, pageParam = 0) => fetchPosts(pageParam))

// New
useInfiniteQuery(['posts'], ({ pageParam = 0 }) => fetchPosts(pageParam))

usePaginatedQuery() wurde zugunsten der keepPreviousData Option entfernt.

Die neue Option keepPreviousData ist sowohl für useQuery als auch für useInfiniteQuery verfügbar und hat den gleichen "verzögernden" Effekt auf Ihre Daten.

tsx
import { useQuery } from 'react-query'

function Page({ page }) {
  const { data } = useQuery(['page', page], fetchPage, {
    keepPreviousData: true,
  })
}
import { useQuery } from 'react-query'

function Page({ page }) {
  const { data } = useQuery(['page', page], fetchPage, {
    keepPreviousData: true,
  })
}

useInfiniteQuery() ist jetzt bidirektional.

Die Benutzeroberfläche von useInfiniteQuery() wurde geändert, um bidirektionale unendliche Listen vollständig zu unterstützen.

  • options.getFetchMore wurde in options.getNextPageParam umbenannt.
  • queryResult.canFetchMore wurde in queryResult.hasNextPage umbenannt.
  • queryResult.fetchMore wurde in queryResult.fetchNextPage umbenannt.
  • queryResult.isFetchingMore wurde in queryResult.isFetchingNextPage umbenannt.
  • Option options.getPreviousPageParam hinzugefügt.
  • Eigenschaft queryResult.hasPreviousPage hinzugefügt.
  • Eigenschaft queryResult.fetchPreviousPage hinzugefügt.
  • Eigenschaft queryResult.isFetchingPreviousPage hinzugefügt.
  • Die data einer unendlichen Query ist jetzt ein Objekt, das die pages und die pageParams enthält, die zum Abrufen der Seiten verwendet wurden: { pages: [data, data, data], pageParams: [...]}

Eine Richtung

tsx
const { data, fetchNextPage, hasNextPage, isFetchingNextPage } =
  useInfiniteQuery(
    'projects',
    ({ pageParam = 0 }) => fetchProjects(pageParam),
    {
      getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
    },
  )
const { data, fetchNextPage, hasNextPage, isFetchingNextPage } =
  useInfiniteQuery(
    'projects',
    ({ pageParam = 0 }) => fetchProjects(pageParam),
    {
      getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
    },
  )

Beide Richtungen

tsx
const {
  data,
  fetchNextPage,
  fetchPreviousPage,
  hasNextPage,
  hasPreviousPage,
  isFetchingNextPage,
  isFetchingPreviousPage,
} = useInfiniteQuery(
  'projects',
  ({ pageParam = 0 }) => fetchProjects(pageParam),
  {
    getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
    getPreviousPageParam: (firstPage, pages) => firstPage.prevCursor,
  },
)
const {
  data,
  fetchNextPage,
  fetchPreviousPage,
  hasNextPage,
  hasPreviousPage,
  isFetchingNextPage,
  isFetchingPreviousPage,
} = useInfiniteQuery(
  'projects',
  ({ pageParam = 0 }) => fetchProjects(pageParam),
  {
    getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
    getPreviousPageParam: (firstPage, pages) => firstPage.prevCursor,
  },
)

Eine Richtung umgekehrt

tsx
const { data, fetchNextPage, hasNextPage, isFetchingNextPage } =
  useInfiniteQuery(
    'projects',
    ({ pageParam = 0 }) => fetchProjects(pageParam),
    {
      select: (data) => ({
        pages: [...data.pages].reverse(),
        pageParams: [...data.pageParams].reverse(),
      }),
      getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
    },
  )
const { data, fetchNextPage, hasNextPage, isFetchingNextPage } =
  useInfiniteQuery(
    'projects',
    ({ pageParam = 0 }) => fetchProjects(pageParam),
    {
      select: (data) => ({
        pages: [...data.pages].reverse(),
        pageParams: [...data.pageParams].reverse(),
      }),
      getNextPageParam: (lastPage, pages) => lastPage.nextCursor,
    },
  )

Infinite Query-Daten enthalten jetzt das Array der Seiten und pageParams, die zum Abrufen dieser Seiten verwendet wurden.

Dies ermöglicht eine einfachere Manipulation der Daten und der Seitenparameter, wie z. B. das Entfernen der ersten Datenseite zusammen mit ihren Parametern.

tsx
queryClient.setQueryData(['projects'], (data) => ({
  pages: data.pages.slice(1),
  pageParams: data.pageParams.slice(1),
}))
queryClient.setQueryData(['projects'], (data) => ({
  pages: data.pages.slice(1),
  pageParams: data.pageParams.slice(1),
}))

useMutation gibt jetzt ein Objekt anstelle eines Arrays zurück.

Obwohl der alte Weg uns warme, wohlige Gefühle gab, als wir useState zum ersten Mal entdeckten, hielten diese nicht lange an. Jetzt ist die Mutationsrückgabe ein einzelnes Objekt.

tsx
// Old:
const [mutate, { status, reset }] = useMutation()

// New:
const { mutate, status, reset } = useMutation()
// Old:
const [mutate, { status, reset }] = useMutation()

// New:
const { mutate, status, reset } = useMutation()

mutation.mutate gibt kein Promise mehr zurück.

  • Die Variable [mutate] wurde zur Funktion mutation.mutate geändert.
  • Funktion mutation.mutateAsync hinzugefügt.

Wir erhielten viele Fragen zu diesem Verhalten, da Benutzer erwarteten, dass das Promise sich wie ein reguläres Promise verhält.

Aus diesem Grund wurde die Funktion mutate in eine mutate und eine mutateAsync Funktion aufgeteilt.

Die Funktion mutate kann bei der Verwendung von Callbacks verwendet werden.

tsx
const { mutate } = useMutation({ mutationFn: addTodo })

mutate('todo', {
  onSuccess: (data) => {
    console.log(data)
  },
  onError: (error) => {
    console.error(error)
  },
  onSettled: () => {
    console.log('settled')
  },
})
const { mutate } = useMutation({ mutationFn: addTodo })

mutate('todo', {
  onSuccess: (data) => {
    console.log(data)
  },
  onError: (error) => {
    console.error(error)
  },
  onSettled: () => {
    console.log('settled')
  },
})

Die Funktion mutateAsync kann bei der Verwendung von async/await verwendet werden.

tsx
const { mutateAsync } = useMutation({ mutationFn: addTodo })

try {
  const data = await mutateAsync('todo')
  console.log(data)
} catch (error) {
  console.error(error)
} finally {
  console.log('settled')
}
const { mutateAsync } = useMutation({ mutationFn: addTodo })

try {
  const data = await mutateAsync('todo')
  console.log(data)
} catch (error) {
  console.error(error)
} finally {
  console.log('settled')
}

Die Objektsyntax für useQuery verwendet jetzt eine kollabierte Konfiguration.

tsx
// Old:
useQuery({
  queryKey: 'posts',
  queryFn: fetchPosts,
  config: { staleTime: Infinity },
})

// New:
useQuery({
  queryKey: 'posts',
  queryFn: fetchPosts,
  staleTime: Infinity,
})
// Old:
useQuery({
  queryKey: 'posts',
  queryFn: fetchPosts,
  config: { staleTime: Infinity },
})

// New:
useQuery({
  queryKey: 'posts',
  queryFn: fetchPosts,
  staleTime: Infinity,
})

Wenn gesetzt, muss die Option QueryOptions.enabled ein Boolean sein (true/false).

Die Query-Option enabled deaktiviert eine Query nun nur noch, wenn der Wert false ist. Bei Bedarf können Werte mit !!userId oder Boolean(userId) umgewandelt werden, und es wird ein hilfreicher Fehler ausgelöst, wenn ein nicht-booleanischer Wert übergeben wird.

Die Option QueryOptions.initialStale wurde entfernt.

Die Option initialStale wurde entfernt und initiale Daten werden nun als normale Daten behandelt. Das bedeutet, wenn initialData bereitgestellt wird, wird die Query beim Mounten standardmäßig neu abgerufen. Wenn Sie nicht sofort neu abrufen möchten, können Sie eine staleTime definieren.

Die Option QueryOptions.forceFetchOnMount wurde durch refetchOnMount: 'always' ersetzt.

Ehrlich gesagt, wir hatten viel zu viele refetchOn____ Optionen, also sollte dies für Klarheit sorgen.

Die Optionen QueryOptions.refetchOnMount gelten nun nur noch für die übergeordnete Komponente und nicht mehr für alle Query-Observer.

Wenn refetchOnMount auf false gesetzt war, wurde verhindert, dass zusätzliche Komponenten beim Mounten neu abgerufen wurden. In Version 3 wird nur die Komponente, in der die Option gesetzt wurde, nicht erneut abgerufen.

QueryOptions.queryFnParamsFilter wurde zugunsten des neuen Objekts QueryFunctionContext entfernt.

Die Option queryFnParamsFilter wurde entfernt, da Query-Funktionen nun ein QueryFunctionContext-Objekt anstelle des Query-Schlüssels erhalten.

Parameter können immer noch innerhalb der Query-Funktion selbst gefiltert werden, da die QueryFunctionContext auch den Query-Schlüssel enthält.

Die Option QueryOptions.notifyOnStatusChange wurde durch die neuen Optionen notifyOnChangeProps und notifyOnChangePropsExclusions abgelöst.

Mit diesen neuen Optionen ist es möglich, granular zu konfigurieren, wann eine Komponente neu rendern soll.

Nur neu rendern, wenn sich die Eigenschaften data oder error ändern.

tsx
import { useQuery } from 'react-query'

function User() {
  const { data } = useQuery(['user'], fetchUser, {
    notifyOnChangeProps: ['data', 'error'],
  })
  return <div>Username: {data.username}</div>
}
import { useQuery } from 'react-query'

function User() {
  const { data } = useQuery(['user'], fetchUser, {
    notifyOnChangeProps: ['data', 'error'],
  })
  return <div>Username: {data.username}</div>
}

Verhindern Sie das erneute Rendern, wenn sich die Eigenschaft isStale ändert.

tsx
import { useQuery } from 'react-query'

function User() {
  const { data } = useQuery(['user'], fetchUser, {
    notifyOnChangePropsExclusions: ['isStale'],
  })
  return <div>Username: {data.username}</div>
}
import { useQuery } from 'react-query'

function User() {
  const { data } = useQuery(['user'], fetchUser, {
    notifyOnChangePropsExclusions: ['isStale'],
  })
  return <div>Username: {data.username}</div>
}

Die Funktion QueryResult.clear() wurde in QueryResult.remove() umbenannt.

Obwohl sie clear hieß, entfernte sie lediglich die Query aus dem Cache. Der Name entspricht nun der Funktionalität.

Die Eigenschaft QueryResult.updatedAt wurde in die Eigenschaften QueryResult.dataUpdatedAt und QueryResult.errorUpdatedAt aufgeteilt.

Da Daten und Fehler gleichzeitig vorhanden sein können, wurde die Eigenschaft updatedAt in dataUpdatedAt und errorUpdatedAt aufgeteilt.

setConsole() wurde durch die neue Funktion setLogger() ersetzt.

tsx
import { setLogger } from 'react-query'

// Log with Sentry
setLogger({
  error: (error) => {
    Sentry.captureException(error)
  },
})

// Log with Winston
setLogger(winston.createLogger())
import { setLogger } from 'react-query'

// Log with Sentry
setLogger({
  error: (error) => {
    Sentry.captureException(error)
  },
})

// Log with Winston
setLogger(winston.createLogger())

React Native erfordert kein Überschreiben des Loggers mehr.

Um die Anzeige von Fehlerbildschirmen in React Native zu verhindern, wenn eine Query fehlschlägt, war es notwendig, die Konsole manuell zu ändern.

tsx
import { setConsole } from 'react-query'

setConsole({
  log: console.log,
  warn: console.warn,
  error: console.warn,
})
import { setConsole } from 'react-query'

setConsole({
  log: console.log,
  warn: console.warn,
  error: console.warn,
})

In Version 3 geschieht dies automatisch, wenn React Query in React Native verwendet wird.

Typescript

QueryStatus wurde von einem Enum in einen Union-Typ geändert

Wenn Sie also die Status-Eigenschaft einer Query oder Mutation gegen eine QueryStatus-Enum-Eigenschaft geprüft haben, müssen Sie dies nun gegen den String-Literal prüfen, den das Enum zuvor für jede Eigenschaft enthielt.

Daher müssen Sie die Enum-Eigenschaften in ihre entsprechenden String-Literale ändern, wie folgt:

  • QueryStatus.Idle -> 'idle'
  • QueryStatus.Loading -> 'loading'
  • QueryStatus.Error -> 'error'
  • QueryStatus.Success -> 'success'

Hier ist ein Beispiel für die Änderungen, die Sie vornehmen müssten:

tsx
- import { useQuery, QueryStatus } from 'react-query'; // [!code --]
+ import { useQuery } from 'react-query'; // [!code ++]

const { data, status } = useQuery(['post', id], () => fetchPost(id))

- if (status === QueryStatus.Loading) { // [!code --]
+ if (status === 'loading') { // [!code ++]
  ...
}

- if (status === QueryStatus.Error) { // [!code --]
+ if (status === 'error') { // [!code ++]
  ...
}
- import { useQuery, QueryStatus } from 'react-query'; // [!code --]
+ import { useQuery } from 'react-query'; // [!code ++]

const { data, status } = useQuery(['post', id], () => fetchPost(id))

- if (status === QueryStatus.Loading) { // [!code --]
+ if (status === 'loading') { // [!code ++]
  ...
}

- if (status === QueryStatus.Error) { // [!code --]
+ if (status === 'error') { // [!code ++]
  ...
}

Neue Features

Query Data Selectors

Die Hooks useQuery und useInfiniteQuery haben nun eine select-Option, um Teile des Query-Ergebnisses auszuwählen oder zu transformieren.

tsx
import { useQuery } from 'react-query'

function User() {
  const { data } = useQuery(['user'], fetchUser, {
    select: (user) => user.username,
  })
  return <div>Username: {data}</div>
}
import { useQuery } from 'react-query'

function User() {
  const { data } = useQuery(['user'], fetchUser, {
    select: (user) => user.username,
  })
  return <div>Username: {data}</div>
}

Setzen Sie die Option notifyOnChangeProps auf ['data', 'error'], um nur dann neu zu rendern, wenn sich die ausgewählten Daten ändern.

Der Hook useQueries() für variable parallele Query-Ausführung

Wünschen Sie sich, eine Schleife mit useQuery ausführen zu können? Die Regeln von Hooks sagen nein, aber mit dem neuen Hook useQueries() können Sie das!

tsx
import { useQueries } from 'react-query'

function Overview() {
  const results = useQueries([
    { queryKey: ['post', 1], queryFn: fetchPost },
    { queryKey: ['post', 2], queryFn: fetchPost },
  ])
  return (
    <ul>
      {results.map(({ data }) => data && <li key={data.id}>{data.title})</li>)}
    </ul>
  )
}
import { useQueries } from 'react-query'

function Overview() {
  const results = useQueries([
    { queryKey: ['post', 1], queryFn: fetchPost },
    { queryKey: ['post', 2], queryFn: fetchPost },
  ])
  return (
    <ul>
      {results.map(({ data }) => data && <li key={data.id}>{data.title})</li>)}
    </ul>
  )
}

Retry/Offline-Mutations

Standardmäßig wird eine Mutation bei einem Fehler nicht wiederholt, aber es ist mit der Option retry möglich.

tsx
const mutation = useMutation({
  mutationFn: addTodo,
  retry: 3,
})
const mutation = useMutation({
  mutationFn: addTodo,
  retry: 3,
})

Wenn Mutationen fehlschlagen, weil das Gerät offline ist, werden sie in derselben Reihenfolge wiederholt, wenn das Gerät wieder online geht.

Mutations speichern

Mutationen können nun im Speicher persistiert und zu einem späteren Zeitpunkt fortgesetzt werden. Weitere Informationen finden Sie in der Mutationsdokumentation.

QueryObserver

Ein QueryObserver kann verwendet werden, um eine Query zu erstellen und/oder zu beobachten.

tsx
const observer = new QueryObserver(queryClient, { queryKey: 'posts' })

const unsubscribe = observer.subscribe((result) => {
  console.log(result)
  unsubscribe()
})
const observer = new QueryObserver(queryClient, { queryKey: 'posts' })

const unsubscribe = observer.subscribe((result) => {
  console.log(result)
  unsubscribe()
})

InfiniteQueryObserver

Ein InfiniteQueryObserver kann verwendet werden, um eine unendliche Query zu erstellen und/oder zu beobachten.

tsx
const observer = new InfiniteQueryObserver(queryClient, {
  queryKey: 'posts',
  queryFn: fetchPosts,
  getNextPageParam: (lastPage, allPages) => lastPage.nextCursor,
  getPreviousPageParam: (firstPage, allPages) => firstPage.prevCursor,
})

const unsubscribe = observer.subscribe((result) => {
  console.log(result)
  unsubscribe()
})
const observer = new InfiniteQueryObserver(queryClient, {
  queryKey: 'posts',
  queryFn: fetchPosts,
  getNextPageParam: (lastPage, allPages) => lastPage.nextCursor,
  getPreviousPageParam: (firstPage, allPages) => firstPage.prevCursor,
})

const unsubscribe = observer.subscribe((result) => {
  console.log(result)
  unsubscribe()
})

QueriesObserver

Ein QueriesObserver kann verwendet werden, um mehrere Queries zu erstellen und/oder zu beobachten.

tsx
const observer = new QueriesObserver(queryClient, [
  { queryKey: ['post', 1], queryFn: fetchPost },
  { queryKey: ['post', 2], queryFn: fetchPost },
])

const unsubscribe = observer.subscribe((result) => {
  console.log(result)
  unsubscribe()
})
const observer = new QueriesObserver(queryClient, [
  { queryKey: ['post', 1], queryFn: fetchPost },
  { queryKey: ['post', 2], queryFn: fetchPost },
])

const unsubscribe = observer.subscribe((result) => {
  console.log(result)
  unsubscribe()
})

Standardoptionen für bestimmte Queries festlegen

Die Methode QueryClient.setQueryDefaults() kann verwendet werden, um Standardoptionen für bestimmte Queries festzulegen.

tsx
queryClient.setQueryDefaults(['posts'], { queryFn: fetchPosts })

function Component() {
  const { data } = useQuery(['posts'])
}
queryClient.setQueryDefaults(['posts'], { queryFn: fetchPosts })

function Component() {
  const { data } = useQuery(['posts'])
}

Standardoptionen für bestimmte Mutationen festlegen

Die Methode QueryClient.setMutationDefaults() kann verwendet werden, um Standardoptionen für bestimmte Mutationen festzulegen.

tsx
queryClient.setMutationDefaults(['addPost'], { mutationFn: addPost })

function Component() {
  const { mutate } = useMutation({ mutationKey: ['addPost'] })
}
queryClient.setMutationDefaults(['addPost'], { mutationFn: addPost })

function Component() {
  const { mutate } = useMutation({ mutationKey: ['addPost'] })
}

useIsFetching()

Der Hook useIsFetching() akzeptiert nun Filter, die verwendet werden können, um beispielsweise einen Spinner nur für bestimmte Arten von Queries anzuzeigen.

tsx
const fetches = useIsFetching({ queryKey: ['posts'] })
const fetches = useIsFetching({ queryKey: ['posts'] })

Kernseparation

Der Kern von React Query ist nun vollständig von React getrennt, was bedeutet, dass er auch eigenständig oder in anderen Frameworks verwendet werden kann. Verwenden Sie den Einstiegspunkt react-query/core, um nur die Kernfunktionalität zu importieren.

tsx
import { QueryClient } from 'react-query/core'
import { QueryClient } from 'react-query/core'

Devtools sind jetzt Teil des Haupt-Repos und des npm-Pakets.

Die Devtools sind nun im react-query-Paket selbst unter dem Import react-query/devtools enthalten. Ersetzen Sie einfach react-query-devtools-Importe durch react-query/devtools.