Add async computed with async callbacks - #686
Conversation
🦋 Changeset detectedLatest commit: 2483777 The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
✅ Deploy Preview for preact-signals-demo ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Size Change: -6.26 kB (-3.02%) Total Size: 201 kB 📦 View Changed
ℹ️ View Unchanged
|
c6d0fc7 to
7a62c6d
Compare
8802208 to
6c7b789
Compare
|
Would it be helpful for future library users to point out pre-emptively in the documentation that async computeds will be reactive until the first await? For example: asyncComputed(async () => {
const client = await authClient();
const user = await client.getUser(userId.value);
return user;
});In this made-up example the async computed won't update when the asyncComputed(async () => {
const id = userId.value;
const client = await authClient();
const user = await client.getUser(id);
return user;
}); |
|
Yes, makes sense to explicitly document this. I thought about it but apparently did not write it 😂 EDIT: ah it's because I kind of did in the blog post I wrote today |
|
Hi! const userDataSignal = asyncComputed(async ({ abortSignal }) => {
const response = await fetch('/api/user', { signal: abortSignal });
return response.json();
});This approach is used, for example, in react-query. |
|
The difference between this primitive and react-query is that it can be used for more than just |
|
True, it’s broader than |
There was a problem hiding this comment.
Hype hype hype, probably one of the most requested features? Would be awesome to see!
the issue being that this is based on
useId()which isn't readily available in React 18 according to the types
useId came out w/ React 18.0, types are probably incorrect there.
Question: When the input variables change for
computedwould you expect us to erasedataanderroror should we retain it and fetch in the background? Alternatively we can add afetchingsignal to have a background indicator.EDIT: Added
runningas a way to differentiate between things
That sounds like a great solution to me.
# Conflicts: # packages/preact/utils/src/index.ts # packages/preact/utils/test/browser/index.test.tsx
✅ Deploy Preview for preact-signals-demo ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Summary
asyncComputed()primitive for ordinary synchronous orasynccallbackspending,settled,failed, anderrorstate while retaining the last successful value and ignoring stale resultscreateModel()automatically follow model disposaluseAsyncComputed()to the Preact and React adapters, including error-boundary behavior and Suspense for externally/model-owned instancesDesign choice
This is the ordinary
async/awaitoption. Signal reads are tracked synchronously, so reactive inputs must be captured before the firstawait:The alternative generator-based prototype re-enters dependency tracking after each yield. Keeping these separate lets us compare familiar async ergonomics against complete cross-suspension tracking.
Hook-created instances render their explicit state and cannot suspend on initial mount because framework hook state does not survive that suspension. For Suspense, create the async computed in a model or above the boundary and pass the instance to
useAsyncComputed(instance, { suspend: true }).