In a React Native app using TanStack Query v5, when would you set networkMode to 'offlineFirst' or 'always' instead of the default 'online'?
answer
- default 'online' gates on onlineManager
- 'offlineFirst' tries once, then pauses retries
- 'always' ignores connectivity entirely
- refetchOnReconnect defaults false under 'always'
- per-query persister implies 'offlineFirst'
basics
~20 sKeep 'online' for network queries. Use 'offlineFirst' when the queryFn might answer offline: it runs once and only pauses retries. Use 'always' when the queryFn never touches the network, such as an on-device storage read.
solid answer
~40 s`networkMode` decides how a query treats `onlineManager`, which in React Native is only as good as its NetInfo wiring. Under the default `'online'`, a query does not run its `queryFn` while offline: it sits at `fetchStatus: 'paused'` and resumes on reconnect. Under `'offlineFirst'`, the `queryFn` runs once regardless; if that attempt fails, retries pause until the device is online. That fits a `queryFn` that can succeed without a connection, for example one that reads a local copy first or goes through a caching layer. Under `'always'`, connectivity is ignored: nothing pauses, retries run and the query can end in `error`, and `refetchOnReconnect` defaults to `false`. That fits a `queryFn` that reads MMKV, SQLite or a computed value. The mode can be set per query or in `defaultOptions`, and mutations have the same option.
code
typescript · 14 linesimport { QueryClient, useQuery } from '@tanstack/react-query';
export const queryClient = new QueryClient({
defaultOptions: { queries: { networkMode: 'online' } },
});
// Reads a locally computed watchlist: no network involved, never pause it.
export function useWatchlistSymbols(readLocal: () => Promise<string[]>) {
return useQuery({
queryKey: ['watchlist', 'symbols'],
queryFn: readLocal,
networkMode: 'always',
});
}go deeper
Recall the three values and that 'online' is the default, pausing network queries while the device is offline.
Explain the start and continue checks, and what paused, errored and resumed look like under each mode.
Match each queryFn to a mode by where its data comes from, and know that a per-query persister and an untrusted connectivity signal both push towards 'offlineFirst'.
Decide how the app behaves when the connectivity signal is wrong, and whether modes are a per-team default or a per-query decision reviewed in code.
## What networkMode controls Every TanStack Query query has a **`networkMode`**: `'online'` (the default), `'offlineFirst'` or `'always'`. It answers one question: *does connectivity, as reported by `onlineManager`, gate this query?* On React Native that manager only knows what the app tells it through NetInfo, so the mode is really a statement about how much you trust that signal and whether the `queryFn` needs the network at all. Two checks inside the retryer make the difference: - **Can it start?** Under `'online'` the first attempt starts only if `onlineManager.isOnline()` is true; under the other two modes it always starts. - **Can it continue?** After a failed attempt and its retry delay, a retry only proceeds if the app is focused and, unless the mode is `'always'`, online. Otherwise it pauses. ## The three modes side by side | | `'online'` (default) | `'offlineFirst'` | `'always'` | |---|---|---|---| | First attempt while offline | paused, not run | runs | runs | | Retries while offline | paused | paused | run, then `error` | | `fetchStatus: 'paused'` possible | yes | yes, after a failed first attempt | no connectivity pause | | `refetchOnReconnect` default | `true` | `true` | `false` | | Fits | plain network requests | a `queryFn` that may answer offline | a `queryFn` that never uses the network | ## When 'offlineFirst' earns its place The TanStack Query docs describe `'offlineFirst'` for a first request that can succeed from a cache, their example being a service worker or HTTP caching on the web. React Native has no service worker, so on a phone the fitting cases are: - a `queryFn` that reads the last saved portfolio from on-device storage and only then goes to the network; - a request routed through a layer you control that can answer from a local copy; - a connectivity signal you do not fully trust: if NetInfo reports disconnected while a request would succeed, `'online'` never tries, whereas `'offlineFirst'` makes one real attempt and pauses only if it fails. It is also the mode TanStack Query picks by itself when a query is given the per-query `persister` option (built with `experimental_createQueryPersister`) and no mode is set, because such a query can be served from storage. ## When 'always' is right Choose `'always'` when the `queryFn` is not a network call: - a read from MMKV, AsyncStorage, expo-sqlite or the file system; - a value computed on the device, such as a derived chart series. Pausing those while offline would be wrong, since they cannot be blocked by a missing connection, and refetching them on reconnect is pointless, which is why `refetchOnReconnect` defaults to `false` in this mode. Turn it back on only if the local source is itself refreshed by a network sync. ## Choosing, in order 1. Does the `queryFn` touch the network? If never, `'always'`. 2. Can it succeed offline some of the time? If yes, `'offlineFirst'`. 3. Otherwise keep `'online'`, and make sure the UI handles `isPaused` on a first load. Set a default in `new QueryClient({ defaultOptions: { queries: { networkMode } } })` and override per query where a screen differs. Remember that focus still gates retries in every mode: a query wired to `AppState` pauses its retries in the background even under `'always'`. ## What networkMode does not do - It does not store anything: persisting the cache across launches is a separate plugin. - It does not queue writes; mutations accept the same option, but how paused writes are stored and replayed is a separate design. - It does not detect connectivity; it only reads what `onlineManager` has been told.
- Why does refetchOnReconnect default to false when networkMode is 'always'?Under `'always'` the query is declared independent of connectivity, so a reconnect says nothing about whether its data changed. TanStack Query sets `refetchOnReconnect` to `networkMode !== 'always'` when you leave it undefined. You can still set it to `true` if the local data is refreshed by a network sync.
- Under 'offlineFirst', what does the user see if the device is offline and the first attempt fails?The `queryFn` runs once and fails; instead of retrying immediately, the retryer pauses because the device is offline, and `fetchStatus` becomes `paused` with the query keeping its current status. It continues the remaining retries when `onlineManager` reports online, as an `'online'` query would.
saying these in an interview costs you the question
- 'offlineFirst' makes TanStack Query save the cache to disk automatically
- 'always' still pauses queries while NetInfo reports the device offline
- networkMode can only be set once, on the QueryClient
- Under 'online' an offline query fails immediately with a network error
- 'offlineFirst' means the queryFn never runs while offline