Skip to content

Commit ef9c853

Browse files
committed
Merge remote-tracking branch 'upstream/main' into feature/angular-stable
2 parents 589b9d1 + dcfc100 commit ef9c853

File tree

203 files changed

+4602
-4989
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

203 files changed

+4602
-4989
lines changed

.github/workflows/autofix.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ jobs:
2424
- name: Fix formatting
2525
run: pnpm prettier:write
2626
- name: Apply fixes
27-
uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c
27+
uses: autofix-ci/action@551dded8c6cc8a1054039c8bc0b8b48c51dfc6ef
2828
with:
2929
commit-message: 'ci: apply automated fixes'

CONTRIBUTING.md

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,63 @@ If you have been assigned to fix an issue or develop a new feature, please follo
5252
- Git stage your required changes and commit (see below commit guidelines).
5353
- Submit PR for review.
5454

55+
### Editing the docs locally and previewing the changes
56+
57+
The documentations for all the TanStack projects are hosted on [tanstack.com](https://tanstack.com), which is a TanStack Start application (https://github.com/TanStack/tanstack.com). You need to run this app locally to preview your changes in the `TanStack/query` docs.
58+
59+
> [!NOTE]
60+
> The website fetches the doc pages from GitHub in production, and searches for them at `../query/docs` in development. Your local clone of `TanStack/query` needs to be in the same directory as the local clone of `TansStack/tanstack.com`.
61+
62+
You can follow these steps to set up the docs for local development:
63+
64+
1. Make a new directory called `tanstack`.
65+
66+
```sh
67+
mkdir tanstack
68+
```
69+
70+
2. Enter that directory and clone the [`TanStack/query`](https://github.com/TanStack/query) and [`TanStack/tanstack.com`](https://github.com/TanStack/tanstack.com) repos.
71+
72+
```sh
73+
cd tanstack
74+
git clone [email protected]:TanStack/query.git
75+
# We probably don't need all the branches and commit history
76+
# from the `tanstack.com` repo, so let's just create a shallow
77+
# clone of the latest version of the `main` branch.
78+
# Read more about shallow clones here:
79+
# https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/#user-content-shallow-clones
80+
git clone [email protected]:TanStack/tanstack.com.git --depth=1 --single-branch --branch=main
81+
```
82+
83+
> [!NOTE]
84+
> Your `tanstack` directory should look like this:
85+
>
86+
> ```
87+
> tanstack/
88+
> |
89+
> +-- query/ (<-- this directory cannot be called anything else!)
90+
> |
91+
> +-- tanstack.com/
92+
> ```
93+
94+
3. Enter the `tanstack/tanstack.com` directory, install the dependencies and run the app in dev mode:
95+
96+
```sh
97+
cd tanstack.com
98+
pnpm i
99+
# The app will run on https://localhost:3000 by default
100+
pnpm dev
101+
```
102+
103+
4. Now you can visit http://localhost:3000/query/latest/docs/overview in the browser and see the changes you make in `tanstack/query/docs` there.
104+
105+
> [!WARNING]
106+
> You will need to update the `docs/config.json` file (in `TanStack/query`) if you add a new documentation page!
107+
108+
You can see the whole process in the screen capture below:
109+
110+
https://github.com/fulopkovacs/form/assets/43729152/9d35a3c3-8153-4e74-9cb2-af275f7a269b
111+
55112
### Running examples
56113

57114
- Make sure you've installed the dependencies in the repo's root directory.
@@ -72,10 +129,6 @@ If you have been assigned to fix an issue or develop a new feature, please follo
72129
pnpm run dev
73130
```
74131

75-
#### Note on `examples/react-native`
76-
77-
React Native example requires Expo to work. Please follow the instructions from example's README.md file to learn more.
78-
79132
#### Note on standalone execution
80133

81134
If you want to run an example without installing dependencies for the whole repo, just follow instructions from the example's README.md file. It will be then run against the latest TanStack Query release.

docs/config.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,10 @@
9999
"label": "TypeScript",
100100
"to": "framework/vue/typescript"
101101
},
102+
{
103+
"label": "Reactivity",
104+
"to": "framework/vue/reactivity"
105+
},
102106
{
103107
"label": "GraphQL",
104108
"to": "framework/vue/graphql"
@@ -116,6 +120,10 @@
116120
"label": "Installation",
117121
"to": "framework/svelte/installation"
118122
},
123+
{
124+
"label": "Devtools",
125+
"to": "framework/svelte/devtools"
126+
},
119127
{
120128
"label": "SSR & SvelteKit",
121129
"to": "framework/svelte/ssr"
@@ -141,6 +149,10 @@
141149
"label": "Quick Start",
142150
"to": "framework/angular/quick-start"
143151
},
152+
{
153+
"label": "Angular HttpClient and other data fetching clients",
154+
"to": "framework/angular/angular-httpclient-and-other-data-fetching-clients"
155+
},
144156
{
145157
"label": "Devtools",
146158
"to": "framework/angular/devtools"
@@ -1050,6 +1062,10 @@
10501062
"label": "Auto Refetching / Polling / Realtime",
10511063
"to": "framework/angular/examples/auto-refetching"
10521064
},
1065+
{
1066+
"label": "Optimistic Updates",
1067+
"to": "framework/angular/examples/optimistic-updates"
1068+
},
10531069
{
10541070
"label": "Pagination",
10551071
"to": "framework/angular/examples/pagination"

docs/eslint/eslint-plugin-query.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ Alternatively, add `@tanstack/query` to the plugins section, and configure the r
9393

9494
## Rules
9595

96-
- [@tanstack/query/exhaustive-deps](../exhaustive-deps)
97-
- [@tanstack/query/no-rest-destructuring](../no-rest-destructuring)
98-
- [@tanstack/query/stable-query-client](../stable-query-client)
99-
- [@tanstack/query/no-unstable-deps](../no-unstable-deps)
100-
- [@tanstack/query/infinite-query-property-order](../infinite-query-property-order)
96+
- [@tanstack/query/exhaustive-deps](./exhaustive-deps)
97+
- [@tanstack/query/no-rest-destructuring](./no-rest-destructuring)
98+
- [@tanstack/query/stable-query-client](./stable-query-client)
99+
- [@tanstack/query/no-unstable-deps](./no-unstable-deps)
100+
- [@tanstack/query/infinite-query-property-order](./infinite-query-property-order)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
id: Angular-HttpClient-and-other-data-fetching-clients
3+
title: Angular HttpClient and other data fetching clients
4+
---
5+
6+
Because TanStack Query's fetching mechanisms are agnostically built on Promises, you can use literally any asynchronous data fetching client, including the browser native `fetch` API, `graphql-request`, and more.
7+
8+
## Using Angular's `HttpClient` for data fetching
9+
10+
`HttpClient` is a powerful and integrated part of Angular, which gives the following benefits:
11+
12+
- Mock responses in unit tests using [provideHttpClientTesting](https://angular.dev/guide/http/testing).
13+
- [Interceptors](https://angular.dev/guide/http/interceptors) can be used for a wide range of functionality including adding authentication headers, performing logging, etc. While some data fetching libraries have their own interceptor system, `HttpClient` interceptors are integrated with Angular's dependency injection system.
14+
- `HttpClient` automatically informs [`PendingTasks`](https://angular.dev/api/core/PendingTasks#), which enables Angular to be aware of pending requests. Unit tests and SSR can use the resulting application _stableness_ information to wait for pending requests to finish. This makes unit testing much easier for [Zoneless](https://angular.dev/guide/experimental/zoneless) applications.
15+
- When using SSR, `HttpClient` will [cache requests](https://angular.dev/guide/ssr#caching-data-when-using-HttpClient) performed on the server. This will prevent unneeded requests on the client. `HttpClient` SSR caching works out of the box. TanStack Query has its own hydration functionality which may be more powerful but requires some setup. Which one fits your needs best depends on your use case.
16+
17+
### Using observables in `queryFn`
18+
19+
As TanStack Query is a promise based library, observables from `HttpClient` need to be converted to promises. This can be done with the `lastValueFrom` or `firstValueFrom` functions from `rxjs`.
20+
21+
```ts
22+
@Component({
23+
// ...
24+
})
25+
class ExampleComponent {
26+
private readonly http = inject(HttpClient)
27+
28+
readonly query = injectQuery(() => ({
29+
queryKey: ['repoData'],
30+
queryFn: () =>
31+
lastValueFrom(
32+
this.http.get('https://api.github.com/repos/tanstack/query'),
33+
),
34+
}))
35+
}
36+
```
37+
38+
> Since Angular is moving towards RxJS as an optional dependency, it's expected that `HttpClient` will also support promises in the future.
39+
>
40+
> Support for observables in TanStack Query for Angular is planned.
41+
42+
## Comparison table
43+
44+
| Data fetching client | Pros | Cons |
45+
| --------------------------------------------------- | --------------------------------------------------- | -------------------------------------------------------------------------- |
46+
| **Angular HttpClient** | Featureful and very well integrated with Angular. | Observables need to be converted to Promises. |
47+
| **Fetch** | Browser native API, so adds nothing to bundle size. | Barebones API which lacks many features. |
48+
| **Specialized libraries such as `graphql-request`** | Specialized features for specific use cases. | If it's not an Angular library it won't integrate well with the framework. |

docs/framework/angular/guides/background-fetching-indicators.md

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,23 @@ ref: docs/framework/react/guides/background-fetching-indicators.md
88

99
```angular-ts
1010
@Component({
11-
selector: 'posts',
11+
selector: 'todos',
1212
template: `
13-
@switch (query.status()) {
14-
@case ('pending') {
15-
Loading...
13+
@if (todosQuery.isPending()) {
14+
Loading...
15+
} @else if (todosQuery.isError()) {
16+
An error has occurred: {{ todosQuery.error().message }}
17+
} @else if (todosQuery.isSuccess()) {
18+
@if (todosQuery.isFetching()) {
19+
Refreshing...
1620
}
17-
@case ('error') {
18-
An error has occurred: {{ query.error()?.message }}
19-
}
20-
@default {
21-
@if (query.isFetching()) {
22-
Refreshing...
23-
}
24-
@for (todo of query.data()) {
25-
<todo [todo]="todo" />
26-
}
21+
@for (todos of todosQuery.data(); track todo.id) {
22+
<todo [todo]="todo" />
2723
}
2824
}
2925
`,
3026
})
31-
export class TodosComponent {
27+
class TodosComponent {
3228
todosQuery = injectQuery(() => ({
3329
queryKey: ['todos'],
3430
queryFn: fetchTodos,

docs/framework/angular/guides/disabling-queries.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ export class TodosComponent {
7070
[//]: # 'Example3'
7171

7272
```angular-ts
73+
import { skipToken, injectQuery } from '@tanstack/query-angular'
74+
7375
@Component({
7476
selector: 'todos',
7577
template: `

docs/framework/angular/guides/queries.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ replace:
1010
'custom hooks': 'services',
1111
'the `useQuery` hook': '`injectQuery`',
1212
'`useQuery`': '`injectQuery`',
13+
"TypeScript will also narrow the type of data correctly if you've checked for pending and error before accessing it.": 'TypeScript will only narrow the type when checking boolean signals such as `isPending` and `isError`.',
1314
}
1415
---
1516

docs/framework/angular/guides/query-options.md

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,28 @@ export class QueriesService {
3131

3232
// usage:
3333

34+
postId = input.required({
35+
transform: numberAttribute,
36+
})
3437
queries = inject(QueriesService)
3538

36-
injectQuery(this.queries.post(1))
37-
injectQueries({
38-
queries: [this.queries.post(1), this.queries.post(2)],
39-
})
39+
postQuery = injectQuery(() => this.queries.post(this.postId()))
40+
4041
queryClient.prefetchQuery(this.queries.post(23))
41-
queryClient.setQueryData(this.queries.post(42).queryKey, newGroups)
42+
queryClient.setQueryData(this.queries.post(42).queryKey, newPost)
4243
```
4344

4445
[//]: # 'Example1'
46+
[//]: # 'Example2'
47+
48+
```ts
49+
// Type inference still works, so query.data will be the return type of select instead of queryFn
50+
queries = inject(QueriesService)
51+
52+
query = injectQuery(() => ({
53+
...groupOptions(1),
54+
select: (data) => data.title,
55+
}))
56+
```
57+
58+
[//]: # 'Example2'

docs/framework/angular/guides/window-focus-refetching.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ replace: { '@tanstack/react-query': '@tanstack/angular-query' }
88
[//]: # 'Example'
99

1010
```ts
11-
bootstrapApplication(AppComponent, {
11+
export const appConfig: ApplicationConfig = {
1212
providers: [
1313
provideTanStackQuery(
1414
new QueryClient({
@@ -20,7 +20,7 @@ bootstrapApplication(AppComponent, {
2020
}),
2121
),
2222
],
23-
})
23+
}
2424
```
2525

2626
[//]: # 'Example'

docs/framework/react/community/community-projects.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ A tool for generating code based on an OpenAPI schema.
6161

6262
Link: https://github.com/fabien0102/openapi-codegen
6363

64+
## OpenAPI Qraft React
65+
66+
Generate type-safe API clients and Hooks for TanStack Query directly from OpenAPI Documents.
67+
Zero-runtime overhead, Proxy-based design, seamless SSR support, and full TanStack Query functionality.
68+
69+
Link: https://github.com/OpenAPI-Qraft/openapi-qraft
70+
6471
## OpenAPI React Query codegen
6572

6673
Generate TanStack Query hooks based on an OpenAPI specification file.

docs/framework/react/guides/advanced-ssr.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,17 @@ title: Advanced Server Rendering
55

66
Welcome to the Advanced Server Rendering guide, where you will learn all about using React Query with streaming, Server Components and the Next.js app router.
77

8-
You might want to read the [Server Rendering & Hydration guide](../ssr) before this one as it teaches the basics for using React Query with SSR, and [Performance & Request Waterfalls](../request-waterfalls) as well as [Prefetching & Router Integration](../prefetching) also contains valuable background.
8+
You might want to read the [Server Rendering & Hydration guide](./ssr) before this one as it teaches the basics for using React Query with SSR, and [Performance & Request Waterfalls](./request-waterfalls) as well as [Prefetching & Router Integration](./prefetching) also contains valuable background.
9+
10+
https://tanstack.com/query/latest/docs/framework/react/guides/ssr
911

1012
Before we start, let's note that while the `initialData` approach outlined in the SSR guide also works with Server Components, we'll focus this guide on the hydration APIs.
1113

1214
## Server Components & Next.js app router
1315

1416
We won't cover Server Components in depth here, but the short version is that they are components that are guaranteed to _only_ run on the server, both for the initial page view and **also on page transitions**. This is similar to how Next.js `getServerSideProps`/`getStaticProps` and Remix `loader` works, as these also always run on the server but while those can only return data, Server Components can do a lot more. The data part is central to React Query however, so let's focus on that.
1517

16-
How do we take what we learned in the Server Rendering guide about [passing data prefetched in framework loaders to the app](../ssr#using-the-hydration-apis) and apply that to Server Components and the Next.js app router? The best way to start thinking about this is to consider Server Components as "just" another framework loader.
18+
How do we take what we learned in the Server Rendering guide about [passing data prefetched in framework loaders to the app](./ssr#using-the-hydration-apis) and apply that to Server Components and the Next.js app router? The best way to start thinking about this is to consider Server Components as "just" another framework loader.
1719

1820
### A quick note on terminology
1921

@@ -392,6 +394,14 @@ function makeQueryClient() {
392394
shouldDehydrateQuery: (query) =>
393395
defaultShouldDehydrateQuery(query) ||
394396
query.state.status === 'pending',
397+
shouldRedactErrors: (error) => {
398+
// We should not catch Next.js server errors
399+
// as that's how Next.js detects dynamic pages
400+
// so we cannot redact them.
401+
// Next.js also automatically redacts errors for us
402+
// with better digests.
403+
return false
404+
},
395405
},
396406
},
397407
})
@@ -593,7 +603,7 @@ For more information, check out the [NextJs Suspense Streaming Example](../../ex
593603

594604
The big upside is that you no longer need to prefetch queries manually to have SSR work, and it even still streams in the result! This gives you phenomenal DX and lower code complexity.
595605

596-
The downside is easiest to explain if we look back at [the complex request waterfall example](../request-waterfalls#code-splitting) in the Performance & Request Waterfalls guide. Server Components with prefetching effectively eliminates the request waterfalls both for the initial page load **and** any subsequent navigation. This prefetch-less approach however will only flatten the waterfalls on the initial page load but ends up the same deep waterfall as the original example on page navigations:
606+
The downside is easiest to explain if we look back at [the complex request waterfall example](./request-waterfalls#code-splitting) in the Performance & Request Waterfalls guide. Server Components with prefetching effectively eliminates the request waterfalls both for the initial page load **and** any subsequent navigation. This prefetch-less approach however will only flatten the waterfalls on the initial page load but ends up the same deep waterfall as the original example on page navigations:
597607

598608
```
599609
1. |> JS for <Feed>

docs/framework/react/guides/caching.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ id: caching
33
title: Caching Examples
44
---
55

6-
> Please thoroughly read the [Important Defaults](../important-defaults) before reading this guide
6+
> Please thoroughly read the [Important Defaults](./important-defaults) before reading this guide
77
88
## Basic Example
99

@@ -23,7 +23,7 @@ Let's assume we are using the default `gcTime` of **5 minutes** and the default
2323
- A second instance of `useQuery({ queryKey: ['todos'], queryFn: fetchTodos })` mounts elsewhere.
2424
- Since the cache already has data for the `['todos']` key from the first query, that data is immediately returned from the cache.
2525
- The new instance triggers a new network request using its query function.
26-
- Note that regardless of whether both `fetchTodos` query functions are identical or not, both queries' [`status`](../../reference/useQuery) are updated (including `isFetching`, `isPending`, and other related values) because they have the same query key.
26+
- Note that regardless of whether both `fetchTodos` query functions are identical or not, both queries' [`status`](../reference/useQuery) are updated (including `isFetching`, `isPending`, and other related values) because they have the same query key.
2727
- 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.
2828
- Both instances of the `useQuery({ queryKey: ['todos'], queryFn: fetchTodos })` query are unmounted and no longer in use.
2929
- 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**).

docs/framework/react/guides/important-defaults.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Out of the box, TanStack Query is configured with **aggressive but sane** defaul
3636

3737
Have a look at the following articles from our Community Resources for further explanations of the defaults:
3838

39-
- [Practical React Query](../../community/tkdodos-blog#1-practical-react-query)
40-
- [React Query as a State Manager](../../community/tkdodos-blog#10-react-query-as-a-state-manager)
39+
- [Practical React Query](../community/tkdodos-blog#1-practical-react-query)
40+
- [React Query as a State Manager](../community/tkdodos-blog#10-react-query-as-a-state-manager)
4141

4242
[//]: # 'Materials'

docs/framework/react/guides/initial-query-data.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,6 @@ const result = useQuery({
170170

171171
## Further reading
172172

173-
For a comparison between `Initial Data` and `Placeholder Data`, have a look at the [Community Resources](../../community/tkdodos-blog#9-placeholder-and-initial-data-in-react-query).
173+
For a comparison between `Initial Data` and `Placeholder Data`, have a look at the [Community Resources](../community/tkdodos-blog#9-placeholder-and-initial-data-in-react-query).
174174

175175
[//]: # 'Materials'

0 commit comments

Comments
 (0)