Skip to content

Commit 9ef86a1

Browse files
committed
feat: transformError; feat: query and mutation flat access result properties
1 parent 172c236 commit 9ef86a1

File tree

8 files changed

+476
-26
lines changed

8 files changed

+476
-26
lines changed

.changeset/itchy-beans-hammer.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"mobx-tanstack-query": minor
3+
---
4+
5+
ability to get access to query\mutation result properties using query._ or mutation._ properties access

.changeset/quiet-geese-dress.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"mobx-tanstack-query": minor
3+
---
4+
5+
`transformError` option for queries and mutations

src/constants.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/**
2+
* A special placeholder that is needed for `enableOnDemand` option
3+
*/
4+
export const enableHolder = () => false;

src/inifinite-query.ts

Lines changed: 201 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ import {
88
QueryKey,
99
InfiniteQueryObserverResult,
1010
InfiniteData,
11+
Updater,
12+
FetchStatus,
13+
QueryStatus,
14+
InfiniteQueryObserverBaseResult,
1115
RefetchOptions,
1216
SetDataOptions,
13-
Updater,
1417
} from '@tanstack/query-core';
1518
import { LinkedAbortController } from 'linked-abort-controller';
1619
import {
@@ -21,6 +24,7 @@ import {
2124
runInAction,
2225
} from 'mobx';
2326

27+
import { enableHolder } from './constants';
2428
import {
2529
InfiniteQueryConfig,
2630
InfiniteQueryDoneListener,
@@ -33,17 +37,54 @@ import {
3337
InfiniteQueryUpdateOptionsAllVariants,
3438
} from './inifinite-query.types';
3539
import { AnyQueryClient, QueryClientHooks } from './query-client.types';
40+
import { QueryFeatures } from './query.types';
3641
import { lazyObserve } from './utils/lazy-observe';
3742

38-
const enableHolder = () => false;
43+
const originalQueryProperties = [
44+
'data',
45+
'dataUpdatedAt',
46+
'error',
47+
'errorUpdatedAt',
48+
'failureCount',
49+
'failureReason',
50+
'errorUpdateCount',
51+
'isError',
52+
'isFetched',
53+
'isFetching',
54+
'isLoading',
55+
'isPending',
56+
'isLoadingError',
57+
'isPaused',
58+
'isPlaceholderData',
59+
'isRefetchError',
60+
'isRefetching',
61+
'isStale',
62+
'isSuccess',
63+
'status',
64+
'fetchStatus',
65+
'fetchNextPage',
66+
'fetchPreviousPage',
67+
'hasNextPage',
68+
'hasPreviousPage',
69+
'isFetchNextPageError',
70+
'isFetchingNextPage',
71+
'isFetchPreviousPageError',
72+
'isFetchingPreviousPage',
73+
] as const satisfies (keyof InfiniteQueryObserverBaseResult)[];
3974

4075
export class InfiniteQuery<
41-
TQueryFnData = unknown,
42-
TError = DefaultError,
43-
TPageParam = unknown,
44-
TData = InfiniteData<TQueryFnData, TPageParam>,
45-
TQueryKey extends QueryKey = QueryKey,
46-
> implements Disposable
76+
TQueryFnData = unknown,
77+
TError = DefaultError,
78+
TPageParam = unknown,
79+
TData = InfiniteData<TQueryFnData, TPageParam>,
80+
TQueryKey extends QueryKey = QueryKey,
81+
>
82+
implements
83+
Disposable,
84+
Pick<
85+
InfiniteQueryObserverBaseResult<TData, TError>,
86+
(typeof originalQueryProperties)[number]
87+
>
4788
{
4889
protected abortController: LinkedAbortController;
4990
protected queryClient: AnyQueryClient;
@@ -58,6 +99,133 @@ export class InfiniteQuery<
5899
TQueryKey
59100
>;
60101

102+
/**
103+
* The last successfully resolved data for the query.
104+
*/
105+
data!: TData | undefined;
106+
/**
107+
* The timestamp for when the query most recently returned the `status` as `"success"`.
108+
*/
109+
dataUpdatedAt!: number;
110+
/**
111+
* The error object for the query, if an error was thrown.
112+
* - Defaults to `null`.
113+
*/
114+
error!: TError | null;
115+
/**
116+
* The timestamp for when the query most recently returned the `status` as `"error"`.
117+
*/
118+
errorUpdatedAt!: number;
119+
/**
120+
* The failure count for the query.
121+
* - Incremented every time the query fails.
122+
* - Reset to `0` when the query succeeds.
123+
*/
124+
failureCount!: number;
125+
/**
126+
* The failure reason for the query retry.
127+
* - Reset to `null` when the query succeeds.
128+
*/
129+
failureReason!: TError | null;
130+
/**
131+
* The sum of all errors.
132+
*/
133+
errorUpdateCount!: number;
134+
/**
135+
* A derived boolean from the `status` variable, provided for convenience.
136+
* - `true` if the query attempt resulted in an error.
137+
*/
138+
isError!: boolean;
139+
/**
140+
* Will be `true` if the query has been fetched.
141+
*/
142+
isFetched!: boolean;
143+
/**
144+
* A derived boolean from the `fetchStatus` variable, provided for convenience.
145+
* - `true` whenever the `queryFn` is executing, which includes initial `pending` as well as background refetch.
146+
*/
147+
isFetching!: boolean;
148+
/**
149+
* Is `true` whenever the first fetch for a query is in-flight.
150+
* - Is the same as `isFetching && isPending`.
151+
*/
152+
isLoading!: boolean;
153+
/**
154+
* Will be `pending` if there's no cached data and no query attempt was finished yet.
155+
*/
156+
isPending!: boolean;
157+
/**
158+
* Will be `true` if the query failed while fetching for the first time.
159+
*/
160+
isLoadingError!: boolean;
161+
/**
162+
* A derived boolean from the `fetchStatus` variable, provided for convenience.
163+
* - The query wanted to fetch, but has been `paused`.
164+
*/
165+
isPaused!: boolean;
166+
/**
167+
* Will be `true` if the data shown is the placeholder data.
168+
*/
169+
isPlaceholderData!: boolean;
170+
/**
171+
* Will be `true` if the query failed while refetching.
172+
*/
173+
isRefetchError!: boolean;
174+
/**
175+
* Is `true` whenever a background refetch is in-flight, which _does not_ include initial `pending`.
176+
* - Is the same as `isFetching && !isPending`.
177+
*/
178+
isRefetching!: boolean;
179+
/**
180+
* Will be `true` if the data in the cache is invalidated or if the data is older than the given `staleTime`.
181+
*/
182+
isStale!: boolean;
183+
/**
184+
* A derived boolean from the `status` variable, provided for convenience.
185+
* - `true` if the query has received a response with no errors and is ready to display its data.
186+
*/
187+
isSuccess!: boolean;
188+
/**
189+
* The status of the query.
190+
* - Will be:
191+
* - `pending` if there's no cached data and no query attempt was finished yet.
192+
* - `error` if the query attempt resulted in an error.
193+
* - `success` if the query has received a response with no errors and is ready to display its data.
194+
*/
195+
status!: QueryStatus;
196+
/**
197+
* The fetch status of the query.
198+
* - `fetching`: Is `true` whenever the queryFn is executing, which includes initial `pending` as well as background refetch.
199+
* - `paused`: The query wanted to fetch, but has been `paused`.
200+
* - `idle`: The query is not fetching.
201+
* - See [Network Mode](https://tanstack.com/query/latest/docs/framework/react/guides/network-mode) for more information.
202+
*/
203+
fetchStatus!: FetchStatus;
204+
/**
205+
* Will be `true` if there is a next page to be fetched (known via the `getNextPageParam` option).
206+
*/
207+
hasNextPage!: boolean;
208+
/**
209+
* Will be `true` if there is a previous page to be fetched (known via the `getPreviousPageParam` option).
210+
*/
211+
hasPreviousPage!: boolean;
212+
/**
213+
* Will be `true` if the query failed while fetching the next page.
214+
*/
215+
isFetchNextPageError!: boolean;
216+
/**
217+
* Will be `true` while fetching the next page with `fetchNextPage`.
218+
*/
219+
isFetchingNextPage!: boolean;
220+
/**
221+
* Will be `true` if the query failed while fetching the previous page.
222+
*/
223+
isFetchPreviousPageError!: boolean;
224+
/**
225+
* Will be `true` while fetching the previous page with `fetchPreviousPage`.
226+
*/
227+
isFetchingPreviousPage!: boolean;
228+
61229
options: InfiniteQueryOptions<
62230
TQueryFnData,
63231
TError,
@@ -159,6 +327,7 @@ export class InfiniteQuery<
159327
this.hooks =
160328
'hooks' in this.queryClient ? this.queryClient.hooks : undefined;
161329
this.isLazy = this.config.lazy;
330+
let transformError: QueryFeatures['transformError'] = config.transformError;
162331

163332
if ('queryFeatures' in queryClient) {
164333
if (this.config.lazy === undefined) {
@@ -168,6 +337,9 @@ export class InfiniteQuery<
168337
this.isEnabledOnResultDemand =
169338
queryClient.queryFeatures.enableOnDemand ?? false;
170339
}
340+
if (!transformError) {
341+
transformError = queryClient.queryFeatures.transformError;
342+
}
171343
}
172344

173345
observable.deep(this, '_result');
@@ -177,6 +349,19 @@ export class InfiniteQuery<
177349
action.bound(this, 'update');
178350
action.bound(this, 'updateResult');
179351

352+
originalQueryProperties.forEach((property) => {
353+
if (this[property]) return;
354+
if (property === 'error' && transformError) {
355+
Object.defineProperty(this, property, {
356+
get: () => transformError(this.result[property]),
357+
});
358+
} else {
359+
Object.defineProperty(this, property, {
360+
get: () => this.result[property],
361+
});
362+
}
363+
});
364+
180365
makeObservable(this);
181366

182367
const isQueryKeyDynamic = typeof queryKeyOrDynamicQueryKey === 'function';
@@ -323,12 +508,18 @@ export class InfiniteQuery<
323508
);
324509
}
325510

511+
/**
512+
* This function allows you to fetch the next "page" of results.
513+
*/
326514
fetchNextPage(options?: FetchNextPageOptions | undefined) {
327-
return this.queryObserver.fetchNextPage(options);
515+
return this._result.fetchNextPage(options);
328516
}
329517

518+
/**
519+
* This function allows you to fetch the previous "page" of results.
520+
*/
330521
fetchPreviousPage(options?: FetchPreviousPageOptions | undefined) {
331-
return this.queryObserver.fetchPreviousPage(options);
522+
return this._result.fetchPreviousPage(options);
332523
}
333524

334525
update(

0 commit comments

Comments
 (0)