Skip to content

Commit 46ad29a

Browse files
authored
feat(queryObserver): add isInitialLoading derived flag (#4244)
* feat(queryObserver): add isInitialLoading derived flag this flag describes isLoading && isFetching and can be used to show a loading spinner for lazy or disabled queries * chore(ci): fix caching apparently, v3 has a fix: actions/setup-node#543 * chore(ci): properly fix token issue as described here: https://stackoverflow.com/questions/52015748/npm-failed-to-replace-env-in-config-npm-token he extra warn output made the caching fail * chore: fix bundlewatch glob * docs: add a section about isInitialLoading to the migration guide
1 parent fec3daa commit 46ad29a

13 files changed

Lines changed: 59 additions & 16 deletions

File tree

.github/workflows/ci.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,16 @@ jobs:
2121
- uses: pnpm/action-setup@v2.2.2
2222
with:
2323
version: 7
24-
- uses: actions/setup-node@v2
24+
- uses: actions/setup-node@v3
2525
with:
2626
node-version: 16.14.2
2727
registry-url: https://registry.npmjs.org/
28+
cache: 'pnpm'
2829
- run: |
29-
pnpm --filter "./packages/**" --filter query install
30+
pnpm --filter "./packages/**" --filter query --prefer-offline install
3031
git config --global user.name 'Tanner Linsley'
3132
git config --global user.email 'tannerlinsley@users.noreply.github.com'
33+
npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
3234
pnpm run cipublish
3335
env:
3436
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}

.github/workflows/pr.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ jobs:
1313
- uses: pnpm/action-setup@v2.2.2
1414
with:
1515
version: 7
16-
- uses: actions/setup-node@v2
16+
- uses: actions/setup-node@v3
1717
with:
1818
node-version: ${{ matrix.node }}
1919
cache: 'pnpm'
2020
- name: Install dependencies
21-
run: pnpm --filter "./packages/**" --filter query install
21+
run: pnpm --filter "./packages/**" --filter query --prefer-offline install
2222
- run: |
2323
pnpm run test:ci
2424
pnpm run test:size

.npmrc

Lines changed: 0 additions & 1 deletion
This file was deleted.

docs/guides/disabling-queries.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ When `enabled` is `false`:
1919
```tsx
2020
function Todos() {
2121
const {
22-
isLoading,
22+
isInitialLoading,
2323
isError,
2424
data,
2525
error,
@@ -45,10 +45,10 @@ function Todos() {
4545
isError ? (
4646
<span>Error: {error.message}</span>
4747
) : (
48-
(isLoading && !isFetching) ? (
49-
<span>Not ready ...</span>
48+
isInitialLoading ? (
49+
<span>Loading...</span>
5050
) : (
51-
<span>Loading...</span>
51+
<span>Not ready ...</span>
5252
)
5353
)
5454
)}
@@ -87,3 +87,13 @@ function Todos() {
8787
)
8888
}
8989
```
90+
91+
### isInitialLoading
92+
93+
Lazy queries will be in `status: 'loading'` right from the start because `loading` means that there is no data yet. This is technically true, however, since we are not currently fetching any data (as the query is not _enabled_), it also means you likely cannot use this flag to show a loading spinner.
94+
95+
If you are using disabled or lazy queries, you can use the `isInitialLoading` flag instead. It's a derived flag that is computed from:
96+
97+
`isLoading && isFetching`
98+
99+
so it will only be true if the query is currently fetching for the first time.

docs/guides/migrating-to-react-query-4.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,17 @@ This will mostly affect `disabled` queries that don't have any `data` yet, as th
112112

113113
Also, have a look at [the guide on dependent queries](../guides/dependent-queries)
114114

115+
#### disabled queries
116+
117+
Due to this change, disabled queries (even temporarily disabled ones) will start in `loading` state. To make migration easier, especially for having a good flag to know when to display a loading spinner, you can check for `isInitialLoading` instead of `isLoading`:
118+
119+
```diff
120+
- isLoading
121+
+ isInitialLoading
122+
```
123+
124+
See also the guide on [disabling queries](../guides/disabling-queries#isInitialLoading)
125+
115126
### new API for `useQueries`
116127

117128
The `useQueries` hook now accepts an object with a `queries` prop as its input. The value of the `queries` prop is an array of queries (this array is identical to what was passed into `useQueries` in v3).

docs/reference/useQuery.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,9 @@ const result = useQuery({
244244
- `isRefetching: boolean`
245245
- Is `true` whenever a background refetch is in-flight, which _does not_ include initial `loading`
246246
- Is the same as `isFetching && !isLoading`
247+
- `isInitialLoading: boolean`
248+
- Is `true` whenever the first fetch for a query is in-flight
249+
- Is the same as `isFetching && isLoading`
247250
- `failureCount: number`
248251
- The failure count for the query.
249252
- Incremented every time the query fails.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@
9696
"bundlewatch": {
9797
"files": [
9898
{
99-
"path": "packages/**/build/umd/*.production.js"
99+
"path": "packages/*/build/umd/*.production.js"
100100
}
101101
]
102102
}

packages/query-core/src/queryObserver.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -547,13 +547,16 @@ export class QueryObserver<
547547
}
548548

549549
const isFetching = fetchStatus === 'fetching'
550+
const isLoading = status === 'loading'
551+
const isError = status === 'error'
550552

551553
const result: QueryObserverBaseResult<TData, TError> = {
552554
status,
553555
fetchStatus,
554-
isLoading: status === 'loading',
556+
isLoading,
555557
isSuccess: status === 'success',
556-
isError: status === 'error',
558+
isError,
559+
isInitialLoading: isLoading && isFetching,
557560
data,
558561
dataUpdatedAt,
559562
error,
@@ -564,13 +567,13 @@ export class QueryObserver<
564567
isFetchedAfterMount:
565568
state.dataUpdateCount > queryInitialState.dataUpdateCount ||
566569
state.errorUpdateCount > queryInitialState.errorUpdateCount,
567-
isFetching: isFetching,
568-
isRefetching: isFetching && status !== 'loading',
569-
isLoadingError: status === 'error' && state.dataUpdatedAt === 0,
570+
isFetching,
571+
isRefetching: isFetching && !isLoading,
572+
isLoadingError: isError && state.dataUpdatedAt === 0,
570573
isPaused: fetchStatus === 'paused',
571574
isPlaceholderData,
572575
isPreviousData,
573-
isRefetchError: status === 'error' && state.dataUpdatedAt !== 0,
576+
isRefetchError: isError && state.dataUpdatedAt !== 0,
574577
isStale: isStale(query, options),
575578
refetch: this.refetch,
576579
remove: this.remove,

packages/query-core/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,7 @@ export interface QueryObserverBaseResult<TData = unknown, TError = unknown> {
373373
isFetching: boolean
374374
isLoading: boolean
375375
isLoadingError: boolean
376+
isInitialLoading: boolean
376377
isPaused: boolean
377378
isPlaceholderData: boolean
378379
isPreviousData: boolean

packages/react-query/src/__tests__/useInfiniteQuery.test.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ describe('useInfiniteQuery', () => {
8484
isFetchingNextPage: false,
8585
isFetchingPreviousPage: false,
8686
isLoading: true,
87+
isInitialLoading: true,
8788
isLoadingError: false,
8889
isPlaceholderData: false,
8990
isPreviousData: false,
@@ -116,6 +117,7 @@ describe('useInfiniteQuery', () => {
116117
isFetchingNextPage: false,
117118
isFetchingPreviousPage: false,
118119
isLoading: false,
120+
isInitialLoading: false,
119121
isLoadingError: false,
120122
isPlaceholderData: false,
121123
isPreviousData: false,

0 commit comments

Comments
 (0)