Skip to content

Commit 57932bd

Browse files
committed
add tag based invalidation docs
1 parent 43bb50a commit 57932bd

File tree

1 file changed

+115
-1
lines changed

1 file changed

+115
-1
lines changed

website/docs/tags.mdx

Lines changed: 115 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,118 @@ title: Tag Based Invalidation
33
sidebar_position: 50
44
---
55

6-
Work in progress. This page is not finished yet.
6+
## What are tags
7+
8+
Tanstack Query encourages invalidating queries with query keys.
9+
But in our opinion query keys are hard to manage, as they are highly variable and not type safe.
10+
11+
For this reason, we introduce a concept of tags.
12+
Tags are a way to mark queries with a specific label. You can easily manipulate the query cache by using these tags.
13+
14+
## How to use tags
15+
16+
You can start by strongly typing the data type that corresponds to each tag:
17+
18+
```ts
19+
const builder = new HttpQueryBuilder().withTagTypes<{
20+
article: ArticleData;
21+
articles: ArticleData[];
22+
refreshable: unknown;
23+
}>();
24+
```
25+
26+
We recommend using single data type for each tag. But in case a tag can be used for multiple data types, you can use a union type or `unknown` type like the `refreshable` tag in the example above.
27+
28+
Then you can use the tags in your queries:
29+
30+
```ts
31+
const listArticlesQuery = builder
32+
.withPath("/articles")
33+
// highlight-next-line
34+
.withTag("articles", "refreshable");
35+
```
36+
37+
The parameter passed to `withTag` can be a function that returns tags. This function will be called with the query data and variables.
38+
39+
```ts
40+
const singleArticleQuery = builder
41+
.withPath("/articles/:id")
42+
// highlight-next-line
43+
.withTag(({ vars }) => ({ type: "article", id: vars.params.id }));
44+
```
45+
46+
Then, you can invalidate the queries in the mutations:
47+
48+
```ts
49+
const deleteArticleMutation = builder
50+
.withPath("/articles/:id")
51+
.withMethod("delete")
52+
// Invalidate the list of articles:
53+
// highlight-next-line
54+
.withUpdates({ type: "articles" })
55+
// Invalidate the single article with given id:
56+
// highlight-next-line
57+
.withUpdates(({ vars }) => ({ type: "article", id: vars.params.id }));
58+
```
59+
60+
## Optimistic updates
61+
62+
You can also use the tags for updating the query cache.
63+
The `withUpdates` method accepts an `updater` function for this purpose.
64+
65+
```ts
66+
const deleteArticleMutation = builder
67+
.withPath("/articles/:id")
68+
.withMethod("delete")
69+
.withUpdates({
70+
type: "articles",
71+
optimistic: true,
72+
// Remove the article with given id from the cache:
73+
// highlight-next-line
74+
updater: ({ vars }, cache) => cache.filter((x) => x.id !== vars.params.id),
75+
});
76+
```
77+
78+
When `optimistic` is set to `true`, the update is done optimistically.
79+
Optimistic updates are applied immediately, before the mutation is completed.
80+
This is useful for providing a better user experience, as the UI can be updated immediately
81+
without waiting for the server response as opposed to the default behavior
82+
where the UI is updated only after the server response is received.
83+
If an error occurs during the mutation, the optimistic update is rolled back automatically.
84+
85+
### Predefined updater functions (Experimental)
86+
87+
:::warning
88+
This feature is experimental and may change in the future.
89+
:::
90+
91+
You can use predefined updater functions for common operations.
92+
93+
```ts
94+
const deleteArticleMutation = builder
95+
.withPath("/articles/:id")
96+
.withMethod("delete")
97+
.withUpdates({
98+
type: "articles",
99+
// highlight-next-line
100+
updater: "delete-params-by-id",
101+
});
102+
```
103+
104+
<details>
105+
<summary>
106+
Explanation
107+
</summary>
108+
109+
The predefined functions are referred as a string. This string has a format of `<operation>-<context>-by-<field>` which can be broken down as follows:
110+
111+
- `<operation>`: The operation to be performed. This can be one of `clear, merge, replace, create, update, upsert, delete, switch`.
112+
- `<context>`: The body of the update that will be used in the operation. This can be one of `data, vars, body, params, search, meta`
113+
- `<field>`: The field to be used in the context to match with the data in the cache. This is usually a unique identifier. This can be any field in the context.
114+
115+
Some examples:
116+
117+
- `delete-params-by-id`: remove the item from a list, where `params.id` matches the `id` field of the item.
118+
- `merge-body-by-id`: merge the `body` to the item in a list, where `body.id` matches the `id` field of the item.
119+
120+
</details>

0 commit comments

Comments
 (0)