sveltejs / svelte

Cybernetically enhanced web apps
https://svelte.dev
MIT License
78.41k stars 4.11k forks source link

Svelte 5 : important recent regression with DexieJs LiveQuery that stopped working #12341

Closed tobiasBora closed 2 months ago

tobiasBora commented 2 months ago

Describe the bug

I recently tried to upgrade my svelte 5 installation (it used to work fine with a previous version of svelte 5), and now I'm basically unable to use Dexie.js as liveQuery just outputs an undefined value if I refresh the page, until I write to the database. This happens even on trivial repositories (I just copied the quickstart of Dexie.js). Since an image is worth a thousand words:

Peek 08-07-2024 09-41

Reproduction

Clone https://github.com/tobiasBora/debugLiveQuery, start with npm run dev -- --open, add a new friend, refresh the page: the friend should be gone. Then add another friend: both the new friend and the old friend should appear.

Logs

No error or non-trivial log of any kind is visible.

System Info

System:
    OS: Linux 6.1 NixOS 24.05 (Uakari) 24.05 (Uakari)
    CPU: (8) x64 Intel(R) Core(TM) i5-8365U CPU @ 1.60GHz
    Memory: 929.63 MB / 15.45 GB
    Container: Yes
    Shell: 5.9 - /home/leo/.nix-profile/bin/zsh
  Binaries:
    Node: 21.6.2 - /nix/store/va3sggfgfb709lm31bzvpjfyapjdy435-nodejs-21.6.2/bin/node
    npm: 10.2.4 - /nix/store/va3sggfgfb709lm31bzvpjfyapjdy435-nodejs-21.6.2/bin/npm
  Browsers:
    Chromium: 122.0.6261.94
  npmPackages:
    svelte: ^5.0.0-next.1 => 5.0.0-next.175

my-app@0.0.1 /tmp/debugLiveQuery/my-app
├── @fontsource/fira-mono@4.5.10
├── @neoconfetti/svelte@1.0.0
├── @sveltejs/adapter-auto@3.2.2
├── @sveltejs/kit@2.5.18
├── @sveltejs/vite-plugin-svelte@3.1.1
├── dexie@4.0.7
├── svelte-check@3.8.4
├── svelte@5.0.0-next.175
├── tslib@2.6.3
├── typescript@5.5.3
└── vite@5.3.3

Severity

blocking all usage of svelte

tobiasBora commented 2 months ago

I tried to check, and the issue appears between next.173 (working) and next.174 (not working), and persists at least until the last version next.175.

trueadm commented 2 months ago

Maybe related to https://github.com/sveltejs/svelte/issues/12330.

tobiasBora commented 2 months ago

Hum… So next.173 is actually working for this specific example, so it seems something broke from 173 to 174. To be honest, in my actual app I also couldn't use 173 because of a mysterious error:

The `this={...}` property of a `<svelte:component>` must be a Svelte component, if defined

so I finally use 172 that seems to work fine for now.

trueadm commented 2 months ago

Hum… So next.173 is actually working for this specific example, so it seems something broke from 173 to 174. To be honest, in my actual app I also couldn't use 173 because of a mysterious error:

The `this={...}` property of a `<svelte:component>` must be a Svelte component, if defined

so I finally use 172 that seems to work fine for now.

Do you use stores? I'm looking through the changes between 173-174 https://github.com/sveltejs/svelte/compare/svelte%405.0.0-next.173...svelte%405.0.0-next.174

tobiasBora commented 2 months ago

In my whole code I do use stores when I got the must be a Svelte component yes, but I have not myself created a store in the MWE that fails for the code that I linked above (but maybe liveQuery used it internally?). Actually you can maybe just bisect the commits with the above MWE I posted? It might be the most efficient here.

trueadm commented 2 months ago

Can you try using the latest version please?

tobiasBora commented 2 months ago

Is it already published? I can only upgrade to 175 to test on my MWE https://github.com/tobiasBora/debugLiveQuery

legowhales commented 2 months ago

Maybe it has to do with the fact that we need to call subscription.unsubscribe() and not subscription() to unsubscribe the liveQuery observable:

From the Dexie's docs:

import { liveQuery } from "dexie";
import { db } from './db';

const friendsObservable = liveQuery (
  () => db.friends
    .where('age')
    .between(50, 75)
    .toArray()
);

// Subscribe
const subscription = friendsObservable.subscribe({
  next: result => console.log("Got result:", JSON.stringify(result)),
  error: error => console.error(error)
});

// Unsubscribe
subscription.unsubscribe();

You could create a wrapper around liveQuery that creates a readable store (and should work for both Svelte 4 & 5):

import { liveQuery } from 'dexie';
import { readable, type Readable } from 'svelte/store';

export function useQuery<T>(querier: () => T | Promise<T>): Readable<T> {
  return readable<T>(undefined, (set) => {
    return liveQuery(querier).subscribe(set).unsubscribe;
  })
}

I don't know why it worked before without doing this though.