Skip to content

Rename cacheTime to gcTime #4829

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jan 20, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/react/community/tkdodos-blog.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ React Query maintainer [TkDodo](https://twitter.com/tkdodo) has a series of blog

## [#1: Practical React Query](https://tkdodo.eu/blog/practical-react-query)

> An advanced introduction to React Query, showing practical tips that go beyond the docs. It covers explaining the defaults (`staleTime` vs. `cacheTime`), concepts like keeping server and client state separate, handling dependencies and creating custom hooks, as well as outlining why the `enabled` option is very powerful. [Read more...](https://tkdodo.eu/blog/practical-react-query)
> An advanced introduction to React Query, showing practical tips that go beyond the docs. It covers explaining the defaults (`staleTime` vs. `gcTime`), concepts like keeping server and client state separate, handling dependencies and creating custom hooks, as well as outlining why the `enabled` option is very powerful. [Read more...](https://tkdodo.eu/blog/practical-react-query)

## [#2: React Query Data Transformations](https://tkdodo.eu/blog/react-query-data-transformations)

Expand Down
4 changes: 2 additions & 2 deletions docs/react/guides/caching.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ This caching example illustrates the story and lifecycle of:
- Inactive Queries
- Garbage Collection

Let's assume we are using the default `cacheTime` of **5 minutes** and the default `staleTime` of `0`.
Let's assume we are using the default `gcTime` of **5 minutes** and the default `staleTime` of `0`.

- A new instance of `useQuery({ queryKey: ['todos'], queryFn: fetchTodos })` mounts.
- Since no other queries have been made with the `['todos']` query key, this query will show a hard loading state and make a network request to fetch the data.
Expand All @@ -26,7 +26,7 @@ Let's assume we are using the default `cacheTime` of **5 minutes** and the defau
- Note that regardless of whether both `fetchTodos` query functions are identical or not, both queries' [`status`](../reference/useQuery) are updated (including `isFetching`, `isLoading`, and other related values) because they have the same query key.
- When the request completes successfully, the cache's data under the `['todos']` key is updated with the new data, and both instances are updated with the new data.
- Both instances of the `useQuery({ queryKey: ['todos'], queryFn: fetchTodos })` query are unmounted and no longer in use.
- Since there are no more active instances of this query, a cache timeout is set using `cacheTime` to delete and garbage collect the query (defaults to **5 minutes**).
- Since there are no more active instances of this query, a garbage collection timeout is set using `gcTime` to delete and garbage collect the query (defaults to **5 minutes**).
- Before the cache timeout has completed, another instance of `useQuery({ queryKey: ['todos'], queyFn: fetchTodos })` mounts. The query immediately returns the available cached data while the `fetchTodos` function is being run in the background. When it completes successfully, it will populate the cache with fresh data.
- The final instance of `useQuery({ queryKey: ['todos'], queryFn: fetchTodos })` unmounts.
- No more instances of `useQuery({ queyKey: ['todos'], queryFn: fetchTodos })` appear within **5 minutes**.
Expand Down
2 changes: 1 addition & 1 deletion docs/react/guides/important-defaults.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Out of the box, TanStack Query is configured with **aggressive but sane** defaul
- Query results that have no more active instances of `useQuery`, `useInfiniteQuery` or query observers are labeled as "inactive" and remain in the cache in case they are used again at a later time.
- By default, "inactive" queries are garbage collected after **5 minutes**.

> To change this, you can alter the default `cacheTime` for queries to something other than `1000 * 60 * 5` milliseconds.
> To change this, you can alter the default `gcTime` for queries to something other than `1000 * 60 * 5` milliseconds.

- Queries that fail are **silently retried 3 times, with exponential backoff delay** before capturing and displaying an error to the UI.

Expand Down
20 changes: 19 additions & 1 deletion docs/react/guides/migrating-to-v5.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,24 @@ The `Hydrate` component has been renamed to `HydrationBoundary`. The `Hydrate` c
- </Hydrate>
+ </HydrationBoundary>
```
```

### Rename `cacheTime` to `gcTime`

Almost everyone gets `cacheTime` wrong. It sounds like "the amount of time that data is cached for", but that is not correct.

`cacheTime` does nothing as long as a query is still in used. It only kicks in as soon as the query becomes unused. After the time has passed, data will be "garbage collected" to avoid the cache from growing.

`gc` is referring to "garbage collect" time. It's a bit more technical, but also a quite [well known abbreviation](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)) in computer science.

```diff
const MINUTE = 1000 * 60;

const queryClient = new QueryClient({
defaultOptions: {
queries: {
- cacheTime: 10 * MINUTE,
+ gcTime: 10 * MINUTE,
},
},
})
```
2 changes: 1 addition & 1 deletion docs/react/guides/mutations.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ const persister = createSyncStoragePersister({
const queryClient = new QueryClient({
defaultOptions: {
queries: {
cacheTime: 1000 * 60 * 60 * 24, // 24 hours
gcTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
})
Expand Down
2 changes: 1 addition & 1 deletion docs/react/guides/prefetching.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const prefetchTodos = async () => {

- If data for this query is already in the cache and **not invalidated**, the data will not be fetched
- If a `staleTime` is passed eg. `prefetchQuery({queryKey: ['todos'], queryFn: fn, staleTime: 5000 })` and the data is older than the specified staleTime, the query will be fetched
- If no instances of `useQuery` appear for a prefetched query, it will be deleted and garbage collected after the time specified in `cacheTime`.
- If no instances of `useQuery` appear for a prefetched query, it will be deleted and garbage collected after the time specified in `gcTime`.

## Manually Priming a Query

Expand Down
6 changes: 3 additions & 3 deletions docs/react/guides/ssr.md
Original file line number Diff line number Diff line change
Expand Up @@ -360,10 +360,10 @@ This refetching of stale queries is a perfect match when caching markup in a CDN

### High memory consumption on server

In case you are creating the `QueryClient` for every request, React Query creates the isolated cache for this client, which is preserved in memory for the `cacheTime` period. That may lead to high memory consumption on server in case of high number of requests during that period.
In case you are creating the `QueryClient` for every request, React Query creates the isolated cache for this client, which is preserved in memory for the `gcTime` period. That may lead to high memory consumption on server in case of high number of requests during that period.

On the server, `cacheTime` defaults to `Infinity` which disables manual garbage collection and will automatically clear memory once a request has finished. If you are explicitly setting a non-Infinity `cacheTime` then you will be responsible for clearing the cache early.
On the server, `gcTime` defaults to `Infinity` which disables manual garbage collection and will automatically clear memory once a request has finished. If you are explicitly setting a non-Infinity `gcTime` then you will be responsible for clearing the cache early.

To clear the cache after it is not needed and to lower memory consumption, you can add a call to [`queryClient.clear()`](../reference/QueryClient#queryclientclear) after the request is handled and dehydrated state has been sent to the client.

Alternatively, you can set a smaller `cacheTime`.
Alternatively, you can set a smaller `gcTime`.
2 changes: 1 addition & 1 deletion docs/react/plugins/createAsyncStoragePersister.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persi
const queryClient = new QueryClient({
defaultOptions: {
queries: {
cacheTime: 1000 * 60 * 60 * 24, // 24 hours
gcTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
})
Expand Down
2 changes: 1 addition & 1 deletion docs/react/plugins/createSyncStoragePersister.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persist
const queryClient = new QueryClient({
defaultOptions: {
queries: {
cacheTime: 1000 * 60 * 60 * 24, // 24 hours
gcTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
})
Expand Down
8 changes: 4 additions & 4 deletions docs/react/plugins/persistQueryClient.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@ This is set of utilities for interacting with "persisters" which save your query

## How It Works

**IMPORTANT** - for persist to work properly, you probably want to pass `QueryClient` a `cacheTime` value to override the default during hydration (as shown above).
**IMPORTANT** - for persist to work properly, you probably want to pass `QueryClient` a `gcTime` value to override the default during hydration (as shown above).

If it is not set when creating the `QueryClient` instance, it will default to `300000` (5 minutes) for hydration, and the stored cache will be discarded after 5 minutes of inactivity. This is the default garbage collection behavior.

It should be set as the same value or higher than persistQueryClient's `maxAge` option. E.g. if `maxAge` is 24 hours (the default) then `cacheTime` should be 24 hours or higher. If lower than `maxAge`, garbage collection will kick in and discard the stored cache earlier than expected.
It should be set as the same value or higher than persistQueryClient's `maxAge` option. E.g. if `maxAge` is 24 hours (the default) then `gcTime` should be 24 hours or higher. If lower than `maxAge`, garbage collection will kick in and discard the stored cache earlier than expected.

You can also pass it `Infinity` to disable garbage collection behavior entirely.

```tsx
const queryClient = new QueryClient({
defaultOptions: {
queries: {
cacheTime: 1000 * 60 * 60 * 24, // 24 hours
gcTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
})
Expand Down Expand Up @@ -187,7 +187,7 @@ import { createSyncStoragePersister } from '@tanstack/query-sync-storage-persist
const queryClient = new QueryClient({
defaultOptions: {
queries: {
cacheTime: 1000 * 60 * 60 * 24, // 24 hours
gcTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
})
Expand Down
2 changes: 1 addition & 1 deletion docs/react/reference/QueryClient.md
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ This distinction is more a "convenience" for ts devs that know which structure w

## `queryClient.setQueryData`

`setQueryData` is a synchronous function that can be used to immediately update a query's cached data. If the query does not exist, it will be created. **If the query is not utilized by a query hook in the default `cacheTime` of 5 minutes, the query will be garbage collected**. To update multiple queries at once and match query keys partially, you need to use [`queryClient.setQueriesData`](#queryclientsetqueriesdata) instead.
`setQueryData` is a synchronous function that can be used to immediately update a query's cached data. If the query does not exist, it will be created. **If the query is not utilized by a query hook in the default `gcTime` of 5 minutes, the query will be garbage collected**. To update multiple queries at once and match query keys partially, you need to use [`queryClient.setQueriesData`](#queryclientsetqueriesdata) instead.

> The difference between using `setQueryData` and `fetchQuery` is that `setQueryData` is sync and assumes that you already synchronously have the data available. If you need to fetch the data asynchronously, it's suggested that you either refetch the query key or use `fetchQuery` to handle the asynchronous fetch.

Expand Down
4 changes: 2 additions & 2 deletions docs/react/reference/useMutation.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const {
status,
} = useMutation({
mutationFn,
cacheTime,
gcTime,
mutationKey,
networkMode,
onError,
Expand All @@ -46,7 +46,7 @@ mutate(variables, {
- **Required**
- A function that performs an asynchronous task and returns a promise.
- `variables` is an object that `mutate` will pass to your `mutationFn`
- `cacheTime: number | Infinity`
- `gcTime: number | Infinity`
- The time in milliseconds that unused/inactive cache data remains in memory. When a mutation's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different cache times are specified, the longest one will be used.
- If set to `Infinity`, will disable garbage collection
- `mutationKey: string`
Expand Down
6 changes: 3 additions & 3 deletions docs/react/reference/useQuery.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const {
} = useQuery({
queryKey,
queryFn,
cacheTime,
gcTime,
enabled,
networkMode,
initialData,
Expand Down Expand Up @@ -91,9 +91,9 @@ const {
- Defaults to `0`
- The time in milliseconds after data is considered stale. This value only applies to the hook it is defined on.
- If set to `Infinity`, the data will never be considered stale
- `cacheTime: number | Infinity`
- `gcTime: number | Infinity`
- Defaults to `5 * 60 * 1000` (5 minutes) or `Infinity` during SSR
- The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different cache times are specified, the longest one will be used.
- The time in milliseconds that unused/inactive cache data remains in memory. When a query's cache becomes unused or inactive, that cache data will be garbage collected after this duration. When different garbage collection times are specified, the longest one will be used.
- If set to `Infinity`, will disable garbage collection
- `queryKeyHashFn: (queryKey: QueryKey) => string`
- Optional
Expand Down
2 changes: 1 addition & 1 deletion docs/vue/guides/mutations.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ function addTodo() {
const client = new QueryClient({
defaultOptions: {
queries: {
cacheTime: 1000 * 60 * 60 * 24, // 24 hours
gcTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
})
Expand Down
6 changes: 3 additions & 3 deletions docs/vue/guides/ssr.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,10 @@ This refetching of stale queries is a perfect match when caching markup in a CDN

### High memory consumption on server

In case you are creating the `QueryClient` for every request, Vue Query creates the isolated cache for this client, which is preserved in memory for the `cacheTime` period. That may lead to high memory consumption on server in case of high number of requests during that period.
In case you are creating the `QueryClient` for every request, Vue Query creates the isolated cache for this client, which is preserved in memory for the `gcTime` period. That may lead to high memory consumption on server in case of high number of requests during that period.

On the server, `cacheTime` defaults to `Infinity` which disables manual garbage collection and will automatically clear memory once a request has finished. If you are explicitly setting a non-Infinity `cacheTime` then you will be responsible for clearing the cache early.
On the server, `gcTime` defaults to `Infinity` which disables manual garbage collection and will automatically clear memory once a request has finished. If you are explicitly setting a non-Infinity `gcTime` then you will be responsible for clearing the cache early.

To clear the cache after it is not needed and to lower memory consumption, you can add a call to [`queryClient.clear()`](../reference/QueryClient#queryclientclear) after the request is handled and dehydrated state has been sent to the client.

Alternatively, you can set a smaller `cacheTime`.
Alternatively, you can set a smaller `gcTime`.
2 changes: 1 addition & 1 deletion examples/react/basic-typescript/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
const queryClient = new QueryClient({
defaultOptions: {
queries: {
cacheTime: 1000 * 60 * 60 * 24, // 24 hours
gcTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
});
Expand Down
2 changes: 1 addition & 1 deletion examples/react/offline/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const location = new ReactLocation();
const queryClient = new QueryClient({
defaultOptions: {
queries: {
cacheTime: 1000 * 60 * 60 * 24, // 24 hours
gcTime: 1000 * 60 * 60 * 24, // 24 hours
staleTime: 2000,
retry: 0,
},
Expand Down
17 changes: 8 additions & 9 deletions examples/react/playground/src/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const queryClient = new QueryClient();

function Root() {
const [staleTime, setStaleTime] = React.useState(1000);
const [cacheTime, setCacheTime] = React.useState(3000);
const [gcTime, setgcTime] = React.useState(3000);
const [localErrorRate, setErrorRate] = React.useState(errorRate);
const [localFetchTimeMin, setLocalFetchTimeMin] =
React.useState(queryTimeMin);
Expand All @@ -48,17 +48,16 @@ function Root() {
queryClient.setDefaultOptions({
queries: {
staleTime,
cacheTime,
gcTime,
},
});
}, [cacheTime, staleTime]);
}, [gcTime, staleTime]);

return (
<QueryClientProvider client={queryClient}>
<p>
The "staleTime" and "cacheTime" durations have been altered in this
example to show how query stale-ness and query caching work on a
granular level
The "staleTime" and "gcTime" durations have been altered in this example
to show how query stale-ness and query caching work on a granular level
</p>
<div>
Stale Time:{" "}
Expand All @@ -72,13 +71,13 @@ function Root() {
/>
</div>
<div>
Cache Time:{" "}
Garbage collection Time:{" "}
<input
type="number"
min="0"
step="1000"
value={cacheTime}
onChange={(e) => setCacheTime(parseFloat(e.target.value, 10))}
value={gcTime}
onChange={(e) => setgcTime(parseFloat(e.target.value, 10))}
style={{ width: "100px" }}
/>
</div>
Expand Down
2 changes: 1 addition & 1 deletion examples/solid/basic-typescript/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { render } from 'solid-js/web'
const queryClient = new QueryClient({
defaultOptions: {
queries: {
cacheTime: 1000 * 60 * 60 * 24, // 24 hours
gcTime: 1000 * 60 * 60 * 24, // 24 hours
},
},
})
Expand Down
2 changes: 1 addition & 1 deletion examples/vue/persister/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const vueQueryOptions: VueQueryPluginOptions = {
queryClientConfig: {
defaultOptions: {
queries: {
cacheTime: 1000 * 60 * 60 * 24,
gcTime: 1000 * 60 * 60 * 24,
staleTime: 1000 * 60 * 60 * 24,
},
},
Expand Down
2 changes: 1 addition & 1 deletion packages/query-core/src/mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export class Mutation<
this.#observers = []
this.state = config.state || getDefaultState()

this.updateCacheTime(this.options.cacheTime)
this.updateGcTime(this.options.gcTime)
this.scheduleGc()
}

Expand Down
2 changes: 1 addition & 1 deletion packages/query-core/src/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ export class Query<
): void {
this.options = { ...this.#defaultOptions, ...options }

this.updateCacheTime(this.options.cacheTime)
this.updateGcTime(this.options.gcTime)
}

protected optionalRemove() {
Expand Down
16 changes: 8 additions & 8 deletions packages/query-core/src/removable.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { isServer, isValidTimeout } from './utils'

export abstract class Removable {
cacheTime!: number
gcTime!: number
#gcTimeout?: ReturnType<typeof setTimeout>

destroy(): void {
Expand All @@ -11,18 +11,18 @@ export abstract class Removable {
protected scheduleGc(): void {
this.clearGcTimeout()

if (isValidTimeout(this.cacheTime)) {
if (isValidTimeout(this.gcTime)) {
this.#gcTimeout = setTimeout(() => {
this.optionalRemove()
}, this.cacheTime)
}, this.gcTime)
}
}

protected updateCacheTime(newCacheTime: number | undefined): void {
// Default to 5 minutes (Infinity for server-side) if no cache time is set
this.cacheTime = Math.max(
this.cacheTime || 0,
newCacheTime ?? (isServer ? Infinity : 5 * 60 * 1000),
protected updateGcTime(newGcTime: number | undefined): void {
// Default to 5 minutes (Infinity for server-side) if no gcTime is set
this.gcTime = Math.max(
this.gcTime || 0,
newGcTime ?? (isServer ? Infinity : 5 * 60 * 1000),
)
}

Expand Down
4 changes: 2 additions & 2 deletions packages/query-core/src/tests/hydration.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,13 @@ describe('dehydration and rehydration', () => {
queryClient.clear()
})

test('should use the cache time from the client', async () => {
test('should use the garbage collection time from the client', async () => {
const queryCache = new QueryCache()
const queryClient = createQueryClient({ queryCache })
await queryClient.prefetchQuery({
queryKey: ['string'],
queryFn: () => fetchData('string'),
cacheTime: 50,
gcTime: 50,
})
const dehydrated = dehydrate(queryClient)
const stringified = JSON.stringify(dehydrated)
Expand Down
Loading