Skip to content

Commit e31bda9

Browse files
docs(solid-query): convert guide docs to ref-based with Solid-style code (#10146)
* docs(react-query/guides): add markers for solid-query guide overrides * docs(solid-query/guides): convert guide docs to ref-based with Solid-style code * docs(config): add solid offline example entry and update lockfile * ci: apply automated fixes * docs(react/guides/caching): unify staleTime wording to passive voice * chore(pnpm-lock.yaml): fix broken lockfile for 'msw' dependency * docs(solid/guides/caching): remove redundant 'StaleNote' override now unified with react * docs(react/guides/caching): remove unused 'StaleNote' markers --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 978fc52 commit e31bda9

Some content is hidden

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

47 files changed

+2808
-175
lines changed

docs/config.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,6 +1419,10 @@
14191419
{
14201420
"label": "Astro",
14211421
"to": "framework/solid/examples/astro"
1422+
},
1423+
{
1424+
"label": "Offline Queries and Mutations",
1425+
"to": "framework/solid/examples/offline"
14221426
}
14231427
]
14241428
},

docs/framework/react/guides/caching.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ Let's assume we are using the default `gcTime` of **5 minutes** and the default
1919
- A new instance of `useQuery({ queryKey: ['todos'], queryFn: fetchTodos })` mounts.
2020
- 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.
2121
- When the network request has completed, the returned data will be cached under the `['todos']` key.
22-
- The hook will mark the data as stale after the configured `staleTime` (defaults to `0`, or immediately).
22+
- The data will be marked as stale after the configured `staleTime` (defaults to `0`, or immediately).
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.

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,13 @@ Out of the box, TanStack Query is configured with **aggressive but sane** defaul
3232

3333
> To change this, you can alter the default `retry` and `retryDelay` options for queries to something other than `3` and the default exponential backoff function.
3434
35+
[//]: # 'StructuralSharing'
36+
3537
- Query results by default are **structurally shared to detect if data has actually changed** and if not, **the data reference remains unchanged** to better help with value stabilization with regards to useMemo and useCallback. If this concept sounds foreign, then don't worry about it! 99.9% of the time you will not need to disable this and it makes your app more performant at zero cost to you.
3638

37-
> Structural sharing only works with JSON-compatible values, any other value types will always be considered as changed. If you are seeing performance issues because of large responses for example, you can disable this feature with the `config.structuralSharing` flag. If you are dealing with non-JSON compatible values in your query responses and still want to detect if data has changed or not, you can provide your own custom function as `config.structuralSharing` to compute a value from the old and new responses, retaining references as required.
39+
[//]: # 'StructuralSharing'
40+
41+
> Structural sharing only works with JSON-compatible values, any other value types will always be considered as changed. If you are seeing performance issues because of large responses for example, you can disable this feature with the `config.structuralSharing` flag. If you are dealing with non-JSON compatible values in your query responses and still want to detect if data has changed or not, you can provide your own custom function as `config.structuralSharing` to compute a value from the old and new responses, retaining references as required.
3842
3943
[//]: # 'Materials'
4044

docs/framework/react/guides/mutations.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,11 +340,14 @@ queryClient.resumePausedMutations()
340340
```
341341

342342
[//]: # 'Example10'
343+
[//]: # 'PersistOfflineIntro'
343344

344345
### Persisting Offline mutations
345346

346347
If you persist offline mutations with the [persistQueryClient plugin](../plugins/persistQueryClient.md), mutations cannot be resumed when the page is reloaded unless you provide a default mutation function.
347348

349+
[//]: # 'PersistOfflineIntro'
350+
348351
This is a technical limitation. When persisting to an external storage, only the state of mutations is persisted, as functions cannot be serialized. After hydration, the component that triggers the mutation might not be mounted, so calling `resumePausedMutations` might yield an error: `No mutationFn found`.
349352

350353
[//]: # 'Example11'
@@ -385,9 +388,12 @@ export default function App() {
385388
```
386389

387390
[//]: # 'Example11'
391+
[//]: # 'OfflineExampleLink'
388392

389393
We also have an extensive [offline example](../examples/offline) that covers both queries and mutations.
390394

395+
[//]: # 'OfflineExampleLink'
396+
391397
## Mutation Scopes
392398

393399
Per default, all mutations run in parallel - even if you invoke `.mutate()` of the same mutation multiple times. Mutations can be given a `scope` with an `id` to avoid that. All mutations with the same `scope.id` will run in serial, which means when they are triggered, they will start in `isPaused: true` state if there is already a mutation for that scope in progress. They will be put into a queue and will automatically resume once their time in the queue has come.

docs/framework/react/guides/parallel-queries.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ function App () {
3535
If the number of queries you need to execute is changing from render to render, you cannot use manual querying since that would violate the rules of hooks. Instead, TanStack Query provides a `useQueries` hook, which you can use to dynamically execute as many queries in parallel as you'd like.
3636

3737
[//]: # 'DynamicParallelIntro'
38+
[//]: # 'DynamicParallelDescription'
3839

3940
`useQueries` accepts an **options object** with a **queries key** whose value is an **array of query objects**. It returns an **array of query results**:
4041

42+
[//]: # 'DynamicParallelDescription'
4143
[//]: # 'Example2'
4244

4345
```tsx

docs/framework/react/guides/queries.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@ title: Queries
77

88
A query is a declarative dependency on an asynchronous source of data that is tied to a **unique key**. A query can be used with any Promise based method (including GET and POST methods) to fetch data from a server. If your method modifies data on the server, we recommend using [Mutations](./mutations.md) instead.
99

10+
[//]: # 'SubscribeDescription'
11+
1012
To subscribe to a query in your components or custom hooks, call the `useQuery` hook with at least:
1113

14+
[//]: # 'SubscribeDescription'
15+
1216
- A **unique key for the query**
1317
- A function that returns a promise that:
1418
- Resolves the data, or

docs/framework/react/guides/query-cancellation.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,4 +208,8 @@ A cancel options object supports the following properties:
208208

209209
## Limitations
210210

211+
[//]: # 'Limitations'
212+
211213
Cancellation does not work when working with `Suspense` hooks: `useSuspenseQuery`, `useSuspenseQueries` and `useSuspenseInfiniteQuery`.
214+
215+
[//]: # 'Limitations'

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@ queryClient.setQueryData(groupOptions(42).queryKey, newGroups)
3333

3434
For Infinite Queries, a separate [`infiniteQueryOptions`](../reference/infiniteQueryOptions.md) helper is available.
3535

36+
[//]: # 'SelectDescription'
37+
3638
You can still override some options at the component level. A very common and useful pattern is to create per-component [`select`](./render-optimizations.md#select) functions:
3739

40+
[//]: # 'SelectDescription'
3841
[//]: # 'Example2'
3942

4043
```ts

docs/framework/react/guides/request-waterfalls.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@ The [Prefetching & Router Integration guide](./prefetching.md) builds on this an
1111

1212
The [Server Rendering & Hydration guide](./ssr.md) teaches you how to prefetch data on the server and pass that data down to the client so you don't have to fetch it again.
1313

14+
[//]: # 'AdvancedSSRLink'
15+
1416
The [Advanced Server Rendering guide](./advanced-ssr.md) further teaches you how to apply these patterns to Server Components and Streaming Server Rendering.
1517

18+
[//]: # 'AdvancedSSRLink'
19+
1620
## What is a Request Waterfall?
1721

1822
A request waterfall is what happens when a request for a resource (code, css, images, data) does not start until _after_ another request for a resource has finished.
@@ -67,6 +71,8 @@ With this as a basis, let's look at a few different patterns that can lead to Re
6771

6872
When a single component first fetches one query, and then another, that's a request waterfall. This can happen when the second query is a [Dependent Query](./dependent-queries.md), that is, it depends on data from the first query when fetching:
6973

74+
[//]: # 'DependentExample'
75+
7076
```tsx
7177
// Get the user
7278
const { data: user } = useQuery({
@@ -89,10 +95,17 @@ const {
8995
})
9096
```
9197

98+
[//]: # 'DependentExample'
99+
92100
While not always feasible, for optimal performance it's better to restructure your API so you can fetch both of these in a single query. In the example above, instead of first fetching `getUserByEmail` to be able to `getProjectsByUser`, introducing a new `getProjectsByUserEmail` query would flatten the waterfall.
93101

102+
[//]: # 'ServerComponentsNote1'
103+
94104
> Another way to mitigate dependent queries without restructuring your API is to move the waterfall to the server where latency is lower. This is the idea behind Server Components which are covered in the [Advanced Server Rendering guide](./advanced-ssr.md).
95105
106+
[//]: # 'ServerComponentsNote1'
107+
[//]: # 'SuspenseSerial'
108+
96109
Another example of serial queries is when you use React Query with Suspense:
97110

98111
```tsx
@@ -122,14 +135,22 @@ const [usersQuery, teamsQuery, projectsQuery] = useSuspenseQueries({
122135
})
123136
```
124137

138+
[//]: # 'SuspenseSerial'
139+
125140
### Nested Component Waterfalls
126141

142+
[//]: # 'NestedIntro'
143+
127144
Nested Component Waterfalls is when both a parent and a child component contains queries, and the parent does not render the child until its query is done. This can happen both with `useQuery` and `useSuspenseQuery`.
128145

146+
[//]: # 'NestedIntro'
147+
129148
If the child renders conditionally based on the data in the parent, or if the child relies on some part of the result being passed down as a prop from the parent to make its query, we have a _dependent_ nested component waterfall.
130149

131150
Let's first look at an example where the child is **not** dependent on the parent.
132151

152+
[//]: # 'NestedExample'
153+
133154
```tsx
134155
function Article({ id }) {
135156
const { data: articleData, isPending } = useQuery({
@@ -161,8 +182,12 @@ function Comments({ id }) {
161182
}
162183
```
163184

185+
[//]: # 'NestedExample'
186+
164187
Note that while `<Comments>` takes a prop `id` from the parent, that id is already available when the `<Article>` renders so there is no reason we could not fetch the comments at the same time as the article. In real world applications, the child might be nested far below the parent and these kinds of waterfalls are often trickier to spot and fix, but for our example, one way to flatten the waterfall would be to hoist the comments query to the parent instead:
165188

189+
[//]: # 'NestedHoistedExample'
190+
166191
```tsx
167192
function Article({ id }) {
168193
const { data: articleData, isPending: articlePending } = useQuery({
@@ -193,12 +218,19 @@ function Article({ id }) {
193218
}
194219
```
195220

221+
[//]: # 'NestedHoistedExample'
222+
[//]: # 'NestedHoistedOutro'
223+
196224
The two queries will now fetch in parallel. Note that if you are using suspense, you'd want to combine these two queries into a single `useSuspenseQueries` instead.
197225

226+
[//]: # 'NestedHoistedOutro'
227+
198228
Another way to flatten this waterfall would be to prefetch the comments in the `<Article>` component, or prefetch both of these queries at the router level on page load or page navigation, read more about this in the [Prefetching & Router Integration guide](./prefetching.md).
199229

200230
Next, let's look at a _Dependent Nested Component Waterfall_.
201231

232+
[//]: # 'DependentNestedExample'
233+
202234
```tsx
203235
function Feed() {
204236
const { data, isPending } = useQuery({
@@ -233,15 +265,21 @@ function GraphFeedItem({ feedItem }) {
233265
}
234266
```
235267

268+
[//]: # 'DependentNestedExample'
269+
236270
The second query `getGraphDataById` is dependent on its parent in two different ways. First of all, it doesn't ever happen unless the `feedItem` is a graph, and second, it needs an `id` from the parent.
237271

238272
```
239273
1. |> getFeed()
240274
2. |> getGraphDataById()
241275
```
242276

277+
[//]: # 'ServerComponentsNote2'
278+
243279
In this example, we can't trivially flatten the waterfall by just hoisting the query to the parent, or even adding prefetching. Just like the dependent query example at the beginning of this guide, one option is to refactor our API to include the graph data in the `getFeed` query. Another more advanced solution is to leverage Server Components to move the waterfall to the server where latency is lower (read more about this in the [Advanced Server Rendering guide](./advanced-ssr.md)) but note that this can be a very big architectural change.
244280

281+
[//]: # 'ServerComponentsNote2'
282+
245283
You can have good performance even with a few query waterfalls here and there, just know they are a common performance concern and be mindful about them. An especially insidious version is when Code Splitting is involved, let's take a look at this next.
246284

247285
### Code Splitting
@@ -323,13 +361,17 @@ In the code split case, it might actually help to hoist the `getGraphDataById` q
323361

324362
This is very much a tradeoff however. You are now including the data fetching code for `getGraphDataById` in the same bundle as `<Feed>`, so evaluate what is best for your case. Read more about how to do this in the [Prefetching & Router Integration guide](./prefetching.md).
325363

364+
[//]: # 'ServerComponentsNote3'
365+
326366
> The tradeoff between:
327367
>
328368
> - Include all data fetching code in the main bundle, even if we seldom use it
329369
> - Put the data fetching code in the code split bundle, but with a request waterfall
330370
>
331371
> is not great and has been one of the motivations for Server Components. With Server Components, it's possible to avoid both, read more about how this applies to React Query in the [Advanced Server Rendering guide](./advanced-ssr.md).
332372
373+
[//]: # 'ServerComponentsNote3'
374+
333375
## Summary and takeaways
334376

335377
Request Waterfalls are a very common and complex performance concern with many tradeoffs. There are many ways to accidentally introduce them into your application:

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

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,56 @@
22
id: background-fetching-indicators
33
title: Background Fetching Indicators
44
ref: docs/framework/react/guides/background-fetching-indicators.md
5-
replace: { 'useMutation[(]': 'useMutation(() => ' }
5+
replace: { 'hook': 'function' }
66
---
7+
8+
[//]: # 'Example'
9+
10+
```tsx
11+
import { Switch, Match, Show, For } from 'solid-js'
12+
13+
function Todos() {
14+
const todosQuery = useQuery(() => ({
15+
queryKey: ['todos'],
16+
queryFn: fetchTodos,
17+
}))
18+
19+
return (
20+
<Switch>
21+
<Match when={todosQuery.isPending}>
22+
<span>Loading...</span>
23+
</Match>
24+
<Match when={todosQuery.isError}>
25+
<span>Error: {todosQuery.error.message}</span>
26+
</Match>
27+
<Match when={todosQuery.isSuccess}>
28+
<Show when={todosQuery.isFetching}>
29+
<div>Refreshing...</div>
30+
</Show>
31+
<div>
32+
<For each={todosQuery.data}>{(todo) => <Todo todo={todo} />}</For>
33+
</div>
34+
</Match>
35+
</Switch>
36+
)
37+
}
38+
```
39+
40+
[//]: # 'Example'
41+
[//]: # 'Example2'
42+
43+
```tsx
44+
import { useIsFetching } from '@tanstack/solid-query'
45+
46+
function GlobalLoadingIndicator() {
47+
const isFetching = useIsFetching()
48+
49+
return (
50+
<Show when={isFetching()}>
51+
<div>Queries are fetching in the background...</div>
52+
</Show>
53+
)
54+
}
55+
```
56+
57+
[//]: # 'Example2'

0 commit comments

Comments
 (0)