Skip to content

Commit c918d2b

Browse files
authored
Merge pull request #7589 from QwikDev/v2-use-async-computed
feat: implement useAsyncComputed$
2 parents 2a3febf + 72ba9f9 commit c918d2b

32 files changed

+931
-204
lines changed

.changeset/little-ways-deny.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@qwik.dev/core': minor
3+
---
4+
5+
feat: new hook - useAsyncComputed$ in replacement of useComputed$ with async operations

packages/docs/src/routes/api/qwik/api.json

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,48 @@
220220
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/shared/qrl/qrl.public.ts",
221221
"mdFile": "core._.md"
222222
},
223+
{
224+
"name": "AsyncComputedFn",
225+
"id": "asynccomputedfn",
226+
"hierarchy": [
227+
{
228+
"name": "AsyncComputedFn",
229+
"id": "asynccomputedfn"
230+
}
231+
],
232+
"kind": "TypeAlias",
233+
"content": "```typescript\nexport type AsyncComputedFn<T> = (ctx: AsyncComputedCtx) => Promise<T>;\n```",
234+
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/use/use-async-computed.ts",
235+
"mdFile": "core.asynccomputedfn.md"
236+
},
237+
{
238+
"name": "AsyncComputedReadonlySignal",
239+
"id": "asynccomputedreadonlysignal",
240+
"hierarchy": [
241+
{
242+
"name": "AsyncComputedReadonlySignal",
243+
"id": "asynccomputedreadonlysignal"
244+
}
245+
],
246+
"kind": "Interface",
247+
"content": "```typescript\nexport interface AsyncComputedReadonlySignal<T = unknown> extends ReadonlySignal<T> \n```\n**Extends:** [ReadonlySignal](#readonlysignal)<!-- -->&lt;T&gt;",
248+
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/reactive-primitives/signal.public.ts",
249+
"mdFile": "core.asynccomputedreadonlysignal.md"
250+
},
251+
{
252+
"name": "AsyncComputedReturnType",
253+
"id": "asynccomputedreturntype",
254+
"hierarchy": [
255+
{
256+
"name": "AsyncComputedReturnType",
257+
"id": "asynccomputedreturntype"
258+
}
259+
],
260+
"kind": "TypeAlias",
261+
"content": "```typescript\nexport type AsyncComputedReturnType<T> = T extends Promise<infer T> ? AsyncComputedReadonlySignal<T> : AsyncComputedReadonlySignal<T>;\n```\n**References:** [AsyncComputedReadonlySignal](#asynccomputedreadonlysignal)",
262+
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/use/use-async-computed.ts",
263+
"mdFile": "core.asynccomputedreturntype.md"
264+
},
223265
{
224266
"name": "cache",
225267
"id": "resourcectx-cache",
@@ -324,6 +366,20 @@
324366
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/use/use-computed.ts",
325367
"mdFile": "core.computedfn.md"
326368
},
369+
{
370+
"name": "ComputedReturnType",
371+
"id": "computedreturntype",
372+
"hierarchy": [
373+
{
374+
"name": "ComputedReturnType",
375+
"id": "computedreturntype"
376+
}
377+
],
378+
"kind": "TypeAlias",
379+
"content": "```typescript\nexport type ComputedReturnType<T> = T extends Promise<any> ? never : ReadonlySignal<T>;\n```\n**References:** [ReadonlySignal](#readonlysignal)",
380+
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/use/use-computed.ts",
381+
"mdFile": "core.computedreturntype.md"
382+
},
327383
{
328384
"name": "ComputedSignal",
329385
"id": "computedsignal",
@@ -2060,7 +2116,7 @@
20602116
}
20612117
],
20622118
"kind": "Interface",
2063-
"content": "```typescript\nexport interface TaskCtx \n```\n\n\n<table><thead><tr><th>\n\nProperty\n\n\n</th><th>\n\nModifiers\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\n[track](#)\n\n\n</td><td>\n\n\n</td><td>\n\n[Tracker](#tracker)\n\n\n</td><td>\n\n\n</td></tr>\n</tbody></table>\n\n\n<table><thead><tr><th>\n\nMethod\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\n[cleanup(callback)](#)\n\n\n</td><td>\n\n\n</td></tr>\n</tbody></table>",
2119+
"content": "```typescript\nexport interface TaskCtx \n```\n\n\n<table><thead><tr><th>\n\nProperty\n\n\n</th><th>\n\nModifiers\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\n[cleanup](#)\n\n\n</td><td>\n\n\n</td><td>\n\n(callback: () =&gt; void) =&gt; void\n\n\n</td><td>\n\n\n</td></tr>\n<tr><td>\n\n[track](#)\n\n\n</td><td>\n\n\n</td><td>\n\n[Tracker](#tracker)\n\n\n</td><td>\n\n\n</td></tr>\n</tbody></table>",
20642120
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/use/use-task.ts",
20652121
"mdFile": "core.taskctx.md"
20662122
},
@@ -2120,6 +2176,20 @@
21202176
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/reactive-primitives/impl/store.ts",
21212177
"mdFile": "core.unwrapstore.md"
21222178
},
2179+
{
2180+
"name": "useAsyncComputed$",
2181+
"id": "useasynccomputed_",
2182+
"hierarchy": [
2183+
{
2184+
"name": "useAsyncComputed$",
2185+
"id": "useasynccomputed_"
2186+
}
2187+
],
2188+
"kind": "Function",
2189+
"content": "Creates a computed signal which is calculated from the given function. A computed signal is a signal which is calculated from other signals. When the signals change, the computed signal is recalculated, and if the result changed, all tasks which are tracking the signal will be re-run and all components that read the signal will be re-rendered.\n\nThe function must be synchronous and must not have any side effects.\n\n\n```typescript\nuseAsyncComputed$: <T>(qrl: AsyncComputedFn<T>) => AsyncComputedReturnType<T>\n```\n\n\n<table><thead><tr><th>\n\nParameter\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\nqrl\n\n\n</td><td>\n\n[AsyncComputedFn](#asynccomputedfn)<!-- -->&lt;T&gt;\n\n\n</td><td>\n\n\n</td></tr>\n</tbody></table>\n**Returns:**\n\n[AsyncComputedReturnType](#asynccomputedreturntype)<!-- -->&lt;T&gt;",
2190+
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/use/use-async-computed.ts",
2191+
"mdFile": "core.useasynccomputed_.md"
2192+
},
21232193
{
21242194
"name": "useComputed$",
21252195
"id": "usecomputed_",
@@ -2130,7 +2200,7 @@
21302200
}
21312201
],
21322202
"kind": "Function",
2133-
"content": "Creates a computed signal which is calculated from the given function. A computed signal is a signal which is calculated from other signals. When the signals change, the computed signal is recalculated, and if the result changed, all tasks which are tracking the signal will be re-run and all components that read the signal will be re-rendered.\n\nThe function must be synchronous and must not have any side effects.\n\n\n```typescript\nuseComputed$: <T>(qrl: ComputedFn<T>) => T extends Promise<any> ? never : ReadonlySignal<T>\n```\n\n\n<table><thead><tr><th>\n\nParameter\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\nqrl\n\n\n</td><td>\n\n[ComputedFn](#computedfn)<!-- -->&lt;T&gt;\n\n\n</td><td>\n\n\n</td></tr>\n</tbody></table>\n**Returns:**\n\nT extends Promise&lt;any&gt; ? never : [ReadonlySignal](#readonlysignal)<!-- -->&lt;T&gt;",
2203+
"content": "Creates a computed signal which is calculated from the given function. A computed signal is a signal which is calculated from other signals. When the signals change, the computed signal is recalculated, and if the result changed, all tasks which are tracking the signal will be re-run and all components that read the signal will be re-rendered.\n\nThe function must be synchronous and must not have any side effects.\n\n\n```typescript\nuseComputed$: <T>(qrl: ComputedFn<T>) => ComputedReturnType<T>\n```\n\n\n<table><thead><tr><th>\n\nParameter\n\n\n</th><th>\n\nType\n\n\n</th><th>\n\nDescription\n\n\n</th></tr></thead>\n<tbody><tr><td>\n\nqrl\n\n\n</td><td>\n\n[ComputedFn](#computedfn)<!-- -->&lt;T&gt;\n\n\n</td><td>\n\n\n</td></tr>\n</tbody></table>\n**Returns:**\n\n[ComputedReturnType](#computedreturntype)<!-- -->&lt;T&gt;",
21342204
"editUrl": "https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/use/use-computed.ts",
21352205
"mdFile": "core.usecomputed_.md"
21362206
},

packages/docs/src/routes/api/qwik/index.mdx

Lines changed: 92 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,37 @@ Expression which should be lazy loaded
119119

120120
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/shared/qrl/qrl.public.ts)
121121

122+
## AsyncComputedFn
123+
124+
```typescript
125+
export type AsyncComputedFn<T> = (ctx: AsyncComputedCtx) => Promise<T>;
126+
```
127+
128+
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/use/use-async-computed.ts)
129+
130+
## AsyncComputedReadonlySignal
131+
132+
```typescript
133+
export interface AsyncComputedReadonlySignal<T = unknown> extends ReadonlySignal<T>
134+
```
135+
136+
**Extends:** [ReadonlySignal](#readonlysignal)&lt;T&gt;
137+
138+
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/reactive-primitives/signal.public.ts)
139+
140+
## AsyncComputedReturnType
141+
142+
```typescript
143+
export type AsyncComputedReturnType<T> =
144+
T extends Promise<infer T>
145+
? AsyncComputedReadonlySignal<T>
146+
: AsyncComputedReadonlySignal<T>;
147+
```
148+
149+
**References:** [AsyncComputedReadonlySignal](#asynccomputedreadonlysignal)
150+
151+
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/use/use-async-computed.ts)
152+
122153
## cache
123154
124155
```typescript
@@ -353,6 +384,17 @@ export type ComputedFn<T> = () => T;
353384

354385
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/use/use-computed.ts)
355386

387+
## ComputedReturnType
388+
389+
```typescript
390+
export type ComputedReturnType<T> =
391+
T extends Promise<any> ? never : ReadonlySignal<T>;
392+
```
393+
394+
**References:** [ReadonlySignal](#readonlysignal)
395+
396+
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/use/use-computed.ts)
397+
356398
## ComputedSignal
357399
358400
A computed signal is a signal which is calculated from other signals. When the signals change, the computed signal is recalculated, and if the result changed, all tasks which are tracking the signal will be re-run and all components that read the signal will be re-rendered.
@@ -8267,31 +8309,26 @@ Description
82678309
</th></tr></thead>
82688310
<tbody><tr><td>
82698311
8270-
[track](#)
8312+
[cleanup](#)
82718313
82728314
</td><td>
82738315
82748316
</td><td>
82758317
8276-
[Tracker](#tracker)
8318+
(callback: () =&gt; void) =&gt; void
82778319
82788320
</td><td>
82798321
82808322
</td></tr>
8281-
</tbody></table>
8282-
8283-
<table><thead><tr><th>
8284-
8285-
Method
8323+
<tr><td>
82868324
8287-
</th><th>
8325+
[track](#)
82888326
8289-
Description
8327+
</td><td>
82908328
8291-
</th></tr></thead>
8292-
<tbody><tr><td>
8329+
</td><td>
82938330
8294-
[cleanup(callback)](#)
8331+
[Tracker](#tracker)
82958332
82968333
</td><td>
82978334
@@ -8433,14 +8470,55 @@ T
84338470
84348471
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/reactive-primitives/impl/store.ts)
84358472
8473+
## useAsyncComputed$
8474+
8475+
Creates a computed signal which is calculated from the given function. A computed signal is a signal which is calculated from other signals. When the signals change, the computed signal is recalculated, and if the result changed, all tasks which are tracking the signal will be re-run and all components that read the signal will be re-rendered.
8476+
8477+
The function must be synchronous and must not have any side effects.
8478+
8479+
```typescript
8480+
useAsyncComputed$: <T>(qrl: AsyncComputedFn<T>) => AsyncComputedReturnType<T>;
8481+
```
8482+
8483+
<table><thead><tr><th>
8484+
8485+
Parameter
8486+
8487+
</th><th>
8488+
8489+
Type
8490+
8491+
</th><th>
8492+
8493+
Description
8494+
8495+
</th></tr></thead>
8496+
<tbody><tr><td>
8497+
8498+
qrl
8499+
8500+
</td><td>
8501+
8502+
[AsyncComputedFn](#asynccomputedfn)&lt;T&gt;
8503+
8504+
</td><td>
8505+
8506+
</td></tr>
8507+
</tbody></table>
8508+
**Returns:**
8509+
8510+
[AsyncComputedReturnType](#asynccomputedreturntype)&lt;T&gt;
8511+
8512+
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/use/use-async-computed.ts)
8513+
84368514
## useComputed$
84378515
84388516
Creates a computed signal which is calculated from the given function. A computed signal is a signal which is calculated from other signals. When the signals change, the computed signal is recalculated, and if the result changed, all tasks which are tracking the signal will be re-run and all components that read the signal will be re-rendered.
84398517
84408518
The function must be synchronous and must not have any side effects.
84418519
84428520
```typescript
8443-
useComputed$: <T>(qrl: ComputedFn<T>) => T extends Promise<any> ? never : ReadonlySignal<T>
8521+
useComputed$: <T>(qrl: ComputedFn<T>) => ComputedReturnType<T>;
84448522
```
84458523
84468524
<table><thead><tr><th>
@@ -8470,7 +8548,7 @@ qrl
84708548
</tbody></table>
84718549
**Returns:**
84728550
8473-
T extends Promise&lt;any&gt; ? never : [ReadonlySignal](#readonlysignal)&lt;T&gt;
8551+
[ComputedReturnType](#computedreturntype)&lt;T&gt;
84748552
84758553
[Edit this section](https://github.com/QwikDev/qwik/tree/main/packages/qwik/src/core/use/use-computed.ts)
84768554

packages/qwik/public.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export {
5757
TaskCtx,
5858
// TODO do we really want to export this?
5959
untrack,
60+
useAsyncComputed$,
6061
useComputed$,
6162
useConstant,
6263
useContext,

packages/qwik/src/core/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export type { UseStylesScoped } from './use/use-styles';
111111
export type { UseSignal } from './use/use-signal';
112112
export type { ContextId } from './use/use-context';
113113
export type { UseStoreOptions } from './use/use-store.public';
114-
export type { ComputedFn } from './use/use-computed';
114+
export type { ComputedFn, ComputedReturnType } from './use/use-computed';
115115
export { useComputedQrl } from './use/use-computed';
116116
export { useSerializerQrl, useSerializer$ } from './use/use-serializer';
117117
export type { OnVisibleTaskOptions, VisibleTaskStrategy } from './use/use-visible-task';
@@ -133,10 +133,13 @@ export { useTaskQrl } from './use/use-task';
133133
export { useTask$ } from './use/use-task-dollar';
134134
export { useVisibleTask$ } from './use/use-visible-task-dollar';
135135
export { useComputed$ } from './use/use-computed';
136+
export type { AsyncComputedFn, AsyncComputedReturnType } from './use/use-async-computed';
137+
export { useAsyncComputedQrl, useAsyncComputed$ } from './use/use-async-computed';
136138
export { useErrorBoundary } from './use/use-error-boundary';
137139
export type { ErrorBoundaryStore } from './shared/error/error-handling';
138140
export {
139141
type ReadonlySignal,
142+
type AsyncComputedReadonlySignal,
140143
type Signal,
141144
type ComputedSignal,
142145
} from './reactive-primitives/signal.public';

packages/qwik/src/core/qwik.core.api.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ import { ValueOrPromise as ValueOrPromise_2 } from '..';
1616
// @public
1717
export const $: <T>(expression: T) => QRL<T>;
1818

19+
// Warning: (ae-forgotten-export) The symbol "AsyncComputedCtx" needs to be exported by the entry point index.d.ts
20+
//
21+
// @public (undocumented)
22+
export type AsyncComputedFn<T> = (ctx: AsyncComputedCtx) => Promise<T>;
23+
24+
// @public (undocumented)
25+
export interface AsyncComputedReadonlySignal<T = unknown> extends ReadonlySignal<T> {
26+
}
27+
28+
// @public (undocumented)
29+
export type AsyncComputedReturnType<T> = T extends Promise<infer T> ? AsyncComputedReadonlySignal<T> : AsyncComputedReadonlySignal<T>;
30+
1931
// @public
2032
export type ClassList = string | undefined | null | false | Record<string, boolean | string | number | null | undefined> | ClassList[];
2133

@@ -74,6 +86,9 @@ export const componentQrl: <PROPS extends Record<any, any>>(componentQrl: QRL<On
7486
// @public (undocumented)
7587
export type ComputedFn<T> = () => T;
7688

89+
// @public (undocumented)
90+
export type ComputedReturnType<T> = T extends Promise<any> ? never : ReadonlySignal<T>;
91+
7792
// @public
7893
export interface ComputedSignal<T> extends ReadonlySignal<T> {
7994
force(): void;
@@ -1582,7 +1597,7 @@ export const _task: (_event: Event, element: Element) => void;
15821597
// @public (undocumented)
15831598
export interface TaskCtx {
15841599
// (undocumented)
1585-
cleanup(callback: () => void): void;
1600+
cleanup: (callback: () => void) => void;
15861601
// (undocumented)
15871602
track: Tracker;
15881603
}
@@ -1620,12 +1635,20 @@ export const untrack: <T>(fn: () => T) => T;
16201635
export const unwrapStore: <T>(value: T) => T;
16211636

16221637
// @public
1623-
export const useComputed$: <T>(qrl: ComputedFn<T>) => T extends Promise<any> ? never : ReadonlySignal<T>;
1638+
export const useAsyncComputed$: <T>(qrl: AsyncComputedFn<T>) => AsyncComputedReturnType<T>;
1639+
1640+
// Warning: (ae-internal-missing-underscore) The name "useAsyncComputedQrl" should be prefixed with an underscore because the declaration is marked as @internal
1641+
//
1642+
// @internal (undocumented)
1643+
export const useAsyncComputedQrl: <T>(qrl: QRL<AsyncComputedFn<T>>) => AsyncComputedReturnType<T>;
1644+
1645+
// @public
1646+
export const useComputed$: <T>(qrl: ComputedFn<T>) => ComputedReturnType<T>;
16241647

16251648
// Warning: (ae-internal-missing-underscore) The name "useComputedQrl" should be prefixed with an underscore because the declaration is marked as @internal
16261649
//
16271650
// @internal (undocumented)
1628-
export const useComputedQrl: <T>(qrl: QRL<ComputedFn<T>>) => T extends Promise<any> ? never : ReadonlySignal<T>;
1651+
export const useComputedQrl: <T>(qrl: QRL<ComputedFn<T>>) => ComputedReturnType<T>;
16291652

16301653
// @public
16311654
export const useConstant: <T>(value: (() => T) | T) => T;

0 commit comments

Comments
 (0)