Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Svelte 5: Runes not tracking async dependencies #11424

Closed
valterkraemer opened this issue May 2, 2024 · 9 comments
Closed

Svelte 5: Runes not tracking async dependencies #11424

valterkraemer opened this issue May 2, 2024 · 9 comments

Comments

@valterkraemer
Copy link
Contributor

valterkraemer commented May 2, 2024

Describe the bug

A value is only considered a dependency of a rune if it is called in the same event loop tick.

Reproduction

This won't re-evaluate when chatId changes. REPL

let derivedId = $derived(Promise.resolve().then(() => chatId))

but using $: it does work. REPL

$: derivedId = Promise.resolve().then(() => id)

workaround is to e.g. do

let derivedId = $derived.by(() => {
  chatId;
  return Promise.resolve().then(() => chatId);
});

My real life example is that Dexie's liveQuery stopped reacting to changes

let chatMessages = $derived(
  liveQuery(() =>
    localDB.chatMessage
      .where({
        chatId,
      })
      .toArray(),
  ),
);

Logs

No response

System Info

-

Severity

annoyance

@trueadm
Copy link
Contributor

trueadm commented May 2, 2024

This is to be expected. Runes are designed to read dependencies sync only – and given the browser has no native way to track async context (yet), this isn't possible to do otherwise.

@valterkraemer
Copy link
Contributor Author

This is to be expected. Runes are designed to read dependencies sync only – and given the browser has no native way to track async context (yet), this isn't possible to do otherwise.

Thanks, that's what I assumed, but couldn't find any documentation/issue related to it.

I guess the compiler could traverse the inside of e.g. $derived and find all the dependencies though 🤔

@trueadm
Copy link
Contributor

trueadm commented May 2, 2024

@valterkraemer What if you call a function from a random npm module? The compiler is limited in context.

@valterkraemer
Copy link
Contributor Author

@valterkraemer What if you call a function from a random npm module? The compiler is limited in context.

I was thinking just the variables used inside of the $derived block, not calls to code outside of it. But yeah, that's probably not a good idea.

Then this would work

let derivedId = $derived.by(() => {
  return Promise.resolve().then(() => chatId);
});

But not this

function myFunc() {
  return Promise.resolve().then(() => chatId);
}

let derivedId = $derived.by(myFunc);

@trueadm
Copy link
Contributor

trueadm commented May 2, 2024

@valterkraemer That would break far too many cases as we now use runtime reactivity rather than compile time reactivity.

@frederikhors
Copy link

Sorry to bother you guys, but what is the idiomatic way to call async methods in new Svelte 5 runes?

@braebo
Copy link
Member

braebo commented Oct 26, 2024

Did you guys every figure out a way to get Dexie liveQuery observables working with runes? I think I'm running in circles 😅

@valterkraemer
Copy link
Contributor Author

Did you guys every figure out a way to get Dexie liveQuery observables working with runes? I think I'm running in circles 😅

What I did as a workaround, as mentioned in the original message, was adding the "reactive dependencies" before liveQuery.

let identity = $derived.by(() => {
    chatMessage.creatorId; // reactive dependency
    
    return liveQuery(() => localDB.identity.get(chatMessage.creatorId));
});

@dummdidumm
Copy link
Member

Closing since both the $state and $derived docs mention that the dependencies need to be synchronous

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants