-
-
Notifications
You must be signed in to change notification settings - Fork 642
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
Is there a plan to make liveQuery more compatible with Svelte5 runes #2075
Comments
Thanks for bringing it up. Also asked on stackoverflow: https://stackoverflow.com/questions/78089371/dexie-livequery-with-svelte-5-runes Need more knowledge about Svelte 5 and runes before I could do anything about it but a PR would be much welcome. Could we introduce some kind of svelte helper library that delivers runes for live queries? A bit like we have for react? |
The recently-added fromStore alongside the wrapper from #1907 worked for me: import { liveQuery } from 'dexie'
import { fromStore } from 'svelte/store'
export const liveQ = q => fromStore({
subscribe: (run, invalidate) =>
liveQuery(q).subscribe(run, invalidate).unsubscribe,
})
// usage
const friends = liveQ(async () => await db.friends.where('age').between(18, 65).toArray())
$inspect(friends.current) |
Hello, I am also trying to use Dexie.js in a Svelte5 project with runes. I started by following the existing tutorial Get started with Dexie in Svelte tutorial. However, I got stuck when trying to make a liveQuery reactive to props/state. I was able to get it working by combining
|
It's correct to recreate the query whenever a closure it depends on changes. In the background the old query will be unsubscribed and a new query subscribed and the result will stay until the new query emits it's initial value. |
We'd need some svelte-specific library to consume live queries more slick with runes. See also my suggested helper in #2089 - it emits errors and loading status but it still need the <script lang="ts">
import { db } from '$lib/store';
import { liveQuery } from 'dexie';
let { namePrefix }: { namePrefix: string } = $props();
const friends = $derived(
liveQuery(
() => db.friends
.where('name')
.startsWith(namePrefix)
.toArray()
)
);
</script>
{#if $friends}
<ul>
{#each $friends as friend (friend.id)}
<li>{friend.name}, {friend.age}</li>
{/each}
</ul>
{/if} Could anyone confirm whether the above code would work? It would be more direct than what's suggested so far. If errors and loading status is requested, then look at how it could be done in #2089. An updated sample using that helper would then be: <script lang="ts">
import { db } from '$lib/store';
import { svelteLiveQuery } from '$lib/svelteLiveQuery'; // or where to put it...
import { liveQuery } from 'dexie';
let { namePrefix }: { namePrefix: string } = $props();
const friendResult = $derived(
svelteLiveQuery(
() => db.friends
.where('name')
.startsWith(namePrefix)
.toArray()
)
);
</script>
<!-- isLoading -->
{#if $friendResult.isLoading}
<p>Loading...</p>
{/if}
<!-- error -->
{#if $friendResult.error}
<p>Error: $friendResult.error</p>
{/if}
<!-- result -->
{#if $friendResult.value}
<ul>
{#each $friendResult.value as friend (friend.id)}
<li>{friend.name}, {friend.age}</li>
{/each}
</ul>
{/if}
|
I've also been struggling with various incantations of this. It works acceptably in certain toy app scenarios, but it's a frustrating nightmare in a production app. I think I've got a working solution now, thanks in large part to standing on the shoulders of @braebo, who posted a solution here (see the "fixed" route). The QueryRune works correctly for simple cases. One gotcha is that it doesn't behave as expected with queries that have derived parameters.So for example, this doesn't work:
( This is not reactive because according to the Svelte docs:
(emphasis mine) Because The least untidy solution I've found is to bring back the concept of ye olde deps array. 😭 I've created a function like this: export function liveRune<T>(
querier: () => T | Promise<T>,
..._dependencies: any[]
): QueryRune<T> | { current: undefined } {
return new QueryRune(liveQuery(querier))
} I can call it like this: const draftQuery = $derived(liveRune(() => getSelectedDraft(book?.id), book?.id)) The function doesn't do anything with the second I've actually extended this function to short circuit if any of the deps are undefined, so cascading loads can behave sanely when waiting for data from a parent query (book, in this example): export function liveRune<T>(
querier: () => T | Promise<T>,
...dependencies: any[]
): QueryRune<T> | { current: undefined } {
if (!dependencies.every((x) => x)) {
return { current: undefined }
}
return new QueryRune(liveQuery(querier))
} Svelte's generally done an excellent job of inferring dependencies, so I'm pretty bummed out that it isn't able to do the right thing without an explicit dependency. But it's the best I've found so far. |
@dusty-phillips thanks for sharing your findings! I'm not sure if this helps, but I've got derived working reliably here. |
With the introduction of runes, store is kinda obsolete. Is there any plan to support runes once svelte5 released?
I use it like this in svelte5
The text was updated successfully, but these errors were encountered: