Skip to content

Commit

Permalink
feat: add initialStale option to queries
Browse files Browse the repository at this point in the history
By default `initialData` is not considered stale, but sometimes you may want it to be, for instance, if your initial data is only a partial subset of an object and you know you will need to refetch the full version immediately after mounting. For this, you can use the `initialStale: true` options.

By setting `initialStale` to `true`, the `initialData` will be considered `stale` and will cause a refetch when the query mounts for the first time.

```js
function Todos() {
  const queryInfo = useQuery('todos', () => fetch('/todos'), {
    initialData: todoListPreview,
    initialStale: true,
  })
}
```
  • Loading branch information
tannerlinsley committed Jun 25, 2020
1 parent 8ec83f4 commit d7048d1
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 5 deletions.
27 changes: 24 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -920,9 +920,9 @@ There may be times when you already have the initial data for a query synchronou

When providing an `initialData` value that is anything other than `undefined`:

- The query `status` will initialize as `success` instead of `loading`
- The query's `isStale` property will initialize as `false` instead of `true`
- The query will not automatically fetch until it is invalidated somehow (eg. window refocus, queryCache refetching, etc)
- The query `status` will initialize in a `success` state instead of `loading`
- The query's `isStale` property will initialize as `false` instead of `true`. This can be overridden by setting the `initialStale` option to `true`
- The query will not automatically fetch until it is invalidated somehow (eg. window refocus, queryCache refetching, `initialStale` is set to `true`, etc)

```js
function Todos() {
Expand Down Expand Up @@ -982,6 +982,23 @@ function Todo({ todoId }) {
}
```
## Marking Initial Data as stale
By default `initialData` is not considered stale, but sometimes you may want it to be, for instance, if your initial data is only a partial subset of an object and you know you will need to refetch the full version immediately after mounting. For this, you can use the `initialStale: true` options.
By setting `initialStale` to `true`, the `initialData` will be considered `stale` and will cause a refetch when the query mounts for the first time.
```js
function Todos() {
const queryInfo = useQuery('todos', () => fetch('/todos'), {
initialData: todoListPreview,
initialStale: true,
})
}
```
> NOTE: Similar to `initialData`, `initialStale` can also be a function for costly calculations, eg. `initialStale: () => isPreview(todoListPreview)`,
## SSR & Initial Data
When using SSR (server-side-rendering) with React Query there are a few things to note:
Expand Down Expand Up @@ -1795,6 +1812,10 @@ const queryInfo = useQuery({
- Optional
- If set, this value will be used as the initial data for the query cache (as long as the query hasn't been created or cached yet)
- If set to a function, the function will be called **once** during the shared/root query initialization, and be expected to synchronously return the initialData
- `initialStale: Boolean | Function() => Boolean`
- Optional
- If set, this will mark the `initialData` any `initialData` provided as stale and will likely cause it to be refetched on mount
- If a function is passed, it will be called only when appropriate to resolve the `initialStale` value. This can be useful if your `initialStale` value is costly to calculate.
- `refetchOnMount: Boolean`
- Optional
- Defaults to `true`
Expand Down
1 change: 1 addition & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const DEFAULT_CONFIG = {
queries: {
queryKeySerializerFn: defaultQueryKeySerializerFn,
queryFn: undefined,
initialStale: undefined,
enabled: true,
retry: 3,
retryDelay: attemptIndex => Math.min(1000 * 2 ** attemptIndex, 30000),
Expand Down
9 changes: 7 additions & 2 deletions src/queryCache.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,8 @@ export function makeQueryCache({ frozen = isServer, defaultConfig } = {}) {
queryCache.prefetchQuery = async (...args) => {
if (
isObject(args[1]) &&
(args[1].hasOwnProperty('throwOnError') || args[1].hasOwnProperty('force'))
(args[1].hasOwnProperty('throwOnError') ||
args[1].hasOwnProperty('force'))
) {
args[3] = args[1]
args[1] = undefined
Expand Down Expand Up @@ -268,7 +269,11 @@ export function makeQueryCache({ frozen = isServer, defaultConfig } = {}) {

const hasInitialData = typeof initialData !== 'undefined'

const isStale = !config.enabled || !hasInitialData
const isStale =
!config.enabled ||
(typeof config.initialStale === 'function'
? config.initialStale()
: config.initialStale ?? !hasInitialData)

const initialStatus = hasInitialData
? statusSuccess
Expand Down
1 change: 1 addition & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ export interface QueryOptions<TResult, TError = Error>
onSuccess?: (data: TResult) => void
onSettled?: (data: TResult | undefined, error: TError | null) => void
initialData?: TResult | (() => TResult | undefined)
initialStale?: boolean | (() => boolean | undefined)
}

export interface PrefetchQueryOptions<TResult, TError = Error>
Expand Down

0 comments on commit d7048d1

Please sign in to comment.