Skip to content

Commit 3001cfd

Browse files
author
Swain Molster
committed
feat: add getQueriesData
1 parent 9868a99 commit 3001cfd

File tree

5 files changed

+152
-12
lines changed

5 files changed

+152
-12
lines changed

README.md

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -484,14 +484,14 @@ cache.updateInfiniteCache(
484484
);
485485
```
486486
487-
#### `getCacheData`
487+
#### `getQueryData`
488488
489489
Get the cached data for a query, if there is any.
490490
491491
```typescript
492492
const cache = useAPICache();
493493

494-
const value = cache.getCacheData(
494+
const value = cache.getQueryData(
495495
// Specify the route + payload that you'd like to get the cached value for.
496496
'GET /messages',
497497
{ filter: 'some-filter' },
@@ -500,18 +500,41 @@ const value = cache.getCacheData(
500500
value; // Message[] | undefined
501501
```
502502
503-
When dealing with a cache entry that was initiated via `useInfiniteAPIQuery` (paginated) prefer using `getInfiniteCacheData` which otherwise behaves the same as `getCacheData`.
503+
When dealing with a cache entry that was initiated via `useInfiniteAPIQuery` (paginated) prefer using `getInfiniteQueryData` which otherwise behaves the same as `getQueryData`.
504504
505505
```typescript
506506
const cache = useAPICache();
507507

508-
const value = cache.getInfiniteCacheData('GET /messages', {
508+
const value = cache.getInfiniteQueryData('GET /messages', {
509509
filter: 'some-filter',
510510
});
511511

512512
value; // { pages: Message[]; }
513513
```
514514
515+
#### `getQueriesData`
516+
517+
Get the cached data for every query of the provided route, by payload.
518+
519+
```typescript
520+
const cache = useAPICache();
521+
522+
// Specify the route.
523+
const value = cache.getQueriesData('GET /messages');
524+
525+
value; // { payload: { filter: string; }; data: Message[] | undefined; }[]
526+
```
527+
528+
If you want to fetch cache data created by `useInfiniteAPIQuery`, prefer using `getInfiniteQueriesData` which otherwise behaves the same as `getQueriesData`.
529+
530+
```typescript
531+
const cache = useAPICache();
532+
533+
const value = cache.getInfiniteQueriesData('GET /messages');
534+
535+
value; // { payload: { filter: string; }; data: { items: } | undefined; }
536+
```
537+
515538
## Test Utility API Reference
516539
517540
`one-query` also provides a testing utility for doing type-safe mocking of API endpoints in tests. This utility is powered by [`msw`](https://github.com/mswjs/msw).

src/cache.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,27 @@ export const createCacheUtils = <Endpoints extends RoughEndpoints>(
8383
},
8484
updateCache: updateCache(),
8585
updateInfiniteCache: updateCache(INFINITE_QUERY_KEY),
86-
getCacheData: (route, payload) =>
86+
getQueryData: (route, payload) =>
8787
client.getQueryData([makeQueryKey(route, payload)]),
88-
getInfiniteCacheData: (route, payload) =>
88+
getInfiniteQueryData: (route, payload) =>
8989
client.getQueryData([INFINITE_QUERY_KEY, makeQueryKey(route, payload)]),
90+
getQueriesData: (route) =>
91+
client
92+
.getQueriesData(createQueryFilterFromSpec({ [route]: 'all' }))
93+
// Don't match infinite queries
94+
.filter(([queryKey]) => queryKey[0] !== INFINITE_QUERY_KEY)
95+
.map(([queryKey, data]) => ({
96+
payload: (queryKey[0] as any).payload,
97+
data,
98+
})),
99+
getInfiniteQueriesData: (route) =>
100+
client
101+
.getQueriesData(createQueryFilterFromSpec({ [route]: 'all' }))
102+
// Only match infinite queries
103+
.filter(([queryKey]) => queryKey[0] === INFINITE_QUERY_KEY)
104+
.map(([queryKey, data]) => ({
105+
payload: (queryKey[1] as any).payload,
106+
data: data as any,
107+
})),
90108
};
91109
};

src/combination.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ type DataOfQuery<Query> = Query extends QueryObserverResult<infer Data>
1717
export type CombinedQueriesDefinedResult<
1818
Queries extends QueryObserverResult[],
1919
> = {
20+
status: 'success';
2021
isLoading: false;
2122
isError: false;
2223
data: {
@@ -32,6 +33,7 @@ export type CombinedQueriesDefinedResult<
3233
export type CombinedQueriesLoadingResult<
3334
Queries extends QueryObserverResult[],
3435
> = {
36+
status: 'loading';
3537
isLoading: true;
3638
isError: false;
3739
data: undefined;
@@ -40,6 +42,7 @@ export type CombinedQueriesLoadingResult<
4042

4143
export type CombinedQueriesErrorResult<Queries extends QueryObserverResult[]> =
4244
{
45+
status: 'error';
4346
isLoading: false;
4447
isError: true;
4548
data: undefined;
@@ -70,6 +73,7 @@ export const combineQueries = <Queries extends QueryObserverResult[]>(
7073
if (queries.some((query) => query.status === 'error')) {
7174
return {
7275
...base,
76+
status: 'error',
7377
isLoading: false,
7478
data: undefined,
7579
isError: true,
@@ -80,6 +84,7 @@ export const combineQueries = <Queries extends QueryObserverResult[]>(
8084
if (queries.some((query) => query.status === 'loading')) {
8185
return {
8286
...base,
87+
status: 'loading',
8388
isLoading: true,
8489
data: undefined,
8590
isError: false,
@@ -89,6 +94,7 @@ export const combineQueries = <Queries extends QueryObserverResult[]>(
8994

9095
return {
9196
...base,
97+
status: 'success',
9298
isLoading: false,
9399
data: queries.map((query) => query.data) as any,
94100
isError: false,

src/hooks.test.tsx

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,7 +1124,7 @@ test('passing a function for `client` is supported', async () => {
11241124
});
11251125
});
11261126

1127-
test('getCacheData', async () => {
1127+
test('getQueryData', async () => {
11281128
network.mock('GET /items', {
11291129
status: 200,
11301130
data: { message: 'test-message' },
@@ -1149,15 +1149,15 @@ test('getCacheData', async () => {
11491149

11501150
return (
11511151
<>
1152-
{cache.getCacheData('GET /items', { filter: 'test-filter' })?.message}
1152+
{cache.getQueryData('GET /items', { filter: 'test-filter' })?.message}
11531153
</>
11541154
);
11551155
});
11561156

11571157
screen2.getByText('test-message');
11581158
});
11591159

1160-
test('getInfiniteCacheData', async () => {
1160+
test('getInfiniteQueryData', async () => {
11611161
network.mock('GET /list', {
11621162
status: 200,
11631163
data: { items: [{ message: 'one' }, { message: 'two' }] },
@@ -1180,7 +1180,7 @@ test('getInfiniteCacheData', async () => {
11801180
const screen2 = render(() => {
11811181
const cache = useAPICache();
11821182

1183-
const value = cache.getInfiniteCacheData('GET /list', {
1183+
const value = cache.getInfiniteQueryData('GET /list', {
11841184
filter: 'test-filter',
11851185
});
11861186

@@ -1191,3 +1191,82 @@ test('getInfiniteCacheData', async () => {
11911191

11921192
screen2.getByText('one,two');
11931193
});
1194+
1195+
test('getQueriesData', async () => {
1196+
network.mock('GET /items', ({ query }) => ({
1197+
status: 200,
1198+
data: { message: query.filter },
1199+
}));
1200+
1201+
// Populate the cache.
1202+
const screen1 = render(() => {
1203+
const query = useCombinedAPIQueries(
1204+
['GET /items', { filter: 'test-filter' }],
1205+
['GET /items', { filter: 'other-filter' }],
1206+
);
1207+
return <>{query.status}</>;
1208+
});
1209+
1210+
await TestingLibrary.waitFor(() => {
1211+
screen1.getByText('success');
1212+
});
1213+
1214+
screen1.unmount();
1215+
1216+
// Now, fetch from the cache.
1217+
1218+
const screen2 = render(() => {
1219+
const cache = useAPICache();
1220+
1221+
const value = cache
1222+
.getQueriesData('GET /items')
1223+
.map(({ data }) => data?.message)
1224+
.join(',');
1225+
1226+
return <>{value}</>;
1227+
});
1228+
1229+
screen2.getByText('test-filter,other-filter');
1230+
});
1231+
1232+
test('getInfiniteQueriesData', async () => {
1233+
network.mock('GET /list', ({ query }) => ({
1234+
status: 200,
1235+
data: { items: [{ message: query.filter }] },
1236+
}));
1237+
1238+
// Populate the cache.
1239+
const screen1 = render(() => {
1240+
const query1 = useInfiniteAPIQuery('GET /list', { filter: 'test-filter' });
1241+
const query2 = useInfiniteAPIQuery('GET /list', { filter: 'other-filter' });
1242+
1243+
return (
1244+
<>
1245+
{query1.status},{query2.status}
1246+
</>
1247+
);
1248+
});
1249+
1250+
await TestingLibrary.waitFor(() => {
1251+
screen1.getByText('success,success');
1252+
});
1253+
1254+
screen1.unmount();
1255+
1256+
// Now, fetch from the cache.
1257+
1258+
const screen2 = render(() => {
1259+
const cache = useAPICache();
1260+
1261+
const value = cache.getInfiniteQueriesData('GET /list');
1262+
1263+
const messages = value
1264+
.flatMap(({ data }) => data!.pages)
1265+
.flatMap((p) => p.items)
1266+
.map((i) => i.message);
1267+
1268+
return <>{messages?.join(',')}</>;
1269+
});
1270+
1271+
screen2.getByText('test-filter,other-filter');
1272+
});

src/types.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,29 @@ export type CacheUtils<Endpoints extends RoughEndpoints> = {
135135
updater: CacheUpdate<InfiniteData<Endpoints[Route]['Response']>>,
136136
) => void;
137137

138-
getCacheData: <Route extends keyof Endpoints & string>(
138+
getQueryData: <Route extends keyof Endpoints & string>(
139139
route: Route,
140140
payload: RequestPayloadOf<Endpoints, Route>,
141141
) => Endpoints[Route]['Response'] | undefined;
142142

143-
getInfiniteCacheData: <Route extends keyof Endpoints & string>(
143+
getInfiniteQueryData: <Route extends keyof Endpoints & string>(
144144
route: Route,
145145
payload: RequestPayloadOf<Endpoints, Route>,
146146
) => InfiniteData<Endpoints[Route]['Response']> | undefined;
147+
148+
getQueriesData: <Route extends keyof Endpoints & string>(
149+
route: Route,
150+
) => {
151+
payload: RequestPayloadOf<Endpoints, Route>;
152+
data: Endpoints[Route]['Response'] | undefined;
153+
}[];
154+
155+
getInfiniteQueriesData: <Route extends keyof Endpoints & string>(
156+
route: Route,
157+
) => {
158+
payload: RequestPayloadOf<Endpoints, Route>;
159+
data: InfiniteData<Endpoints[Route]['Response']> | undefined;
160+
}[];
147161
};
148162

149163
export type APIQueryHooks<Endpoints extends RoughEndpoints> = {

0 commit comments

Comments
 (0)