Open dusty-phillips opened 10 months ago
I'm also seeing this.
In addition to the magic-update that Dusty mentioned when you log in, for me it magically updates to logged in upon navigation to a page that accesses Dexie (e.g. via a liveQuery on the page). But it does not magically update if I navigate to a page that doesn't access Dexie.
(@dusty-phillips thanks for excellent your write-up on Dexie Cloud, by the way!)
Did some poking around in the source this morning. Found these lines that seem to have the specific purpose of preventing this problem. I'm not sure why they aren't accomplishing that though.
When I get a chance (i.e. probably tomorrow), I'll try debugging the package locally and see what currentUser is after those lines.
I've found a solution. The commit which added those lines says they are only run when db.open
is called. [The docs on db.open
](https://dexie.org/docs/Dexie/Dexie.open()) say that it's called either explicitly (which I'm not doing) or implicitly on first query. (That would explain the behavior I was seeing where it suddenly updates to logged in once a Dexie query is made.)
So one solution is to await db.open
before using currentUser
. I did this in my root layout's loader (mostly since my root layout was where I was seeing the problem):
import { browser } from '$app/environment';
import db from '$lib/db';
import type { LayoutLoad } from './$types';
export const load: LayoutLoad = async () => {
if (browser) {
await db.open();
}
return {
db,
};
};
Then in my root layout Svelte component:
<script lang="ts">
import type { LayoutData } from './$types';
export let data: LayoutData;
const db = data.db;
let user = db.cloud.currentUser;
</script>
<slot />
<footer>
{#if $user.isLoggedIn}
Logged in as {$user.name}.
{:else}
<button on:click={() => db.cloud.login()}>Log in</button>
{/if}
</footer>
Actually, since db.currentUser
is an observable, it might be sufficient to just call db.open
in an onMount
hook, without awaiting it. 🤔 Awaiting it feels more "correct", though.
Thanks @tylermercer for these findings. In all my samples I have had at least one liveQuery going on somewhere, and they will implicitly open the db, so I have missed this scenario. We should probably let our observables in db.cloud trigger a db.open when subscribed to, the same way as liveQueries do. But doing db.open() somewhere in the application start fixes it for now.
Thanks @tylermercer for these findings.
@dfahlander thank you for the clean git history that made it easy to track things down!
We should probably let our observables in db.cloud trigger a db.open when subscribed to, the same way as liveQueries do.
That sounds like a good solution. The behavior would be more intuitive.
But doing db.open() somewhere in the application start fixes it for now.
Can we put a note about the need for this in the docs? I can open a PR for it tomorrow.
Ah, good research! I've been using Dexie successfully with Svelte for a couple months and I was tempted to close this because it didn't seem to be an issue anymore. My production app opens the DB on mount, so I was getting the correct behaviour for reasons I didn't understand.
...it might be sufficient to just call db.open in an onMount hook, without awaiting it. 🤔 Awaiting it feels more "correct", though.
I have this problem in Sveltekit and came here because this approach seemed to fix it. However there is some condition which affects my system probably on the first sign in or sign out of a new build. There,
db.open
, nothing works (can't remember the exact symptoms). db.open
in effectively onMount, browser only, the await hangs . See below.I'm not sure how to step into that, but it seems like I at least running on Chrome based browsers need no await, it's fire and forget...
let count = 1
console.log(count++)
// await db.open() // Never returns, on 1st hit
db.open()
console.log(count++) // Never gets here if await the open.
let usr = db.cloud.currentUser
I got it going by wrapping the db.open()
call in a timeout, so when it hangs I just kill it off anyway. It returns fast (when it's not needed), but I can't find a test which detects that before calling it, and if I await
it in one scenario, in the other. The two scenarios being: (1) user not signed in; (2) user signed in.
That seems to work.
In yet another episode of "Dusty's Repro Is Not At all Minimal": https://github.com/dusty-phillips/dexie-cloud-svelte-repro (Sorry about that).
This repo is actually a standard svelte-kit install with loads of base files. I've added Dexie and dexie-cloud-addon (latest betas) as dependencies.
The repro itself actually is pretty minimal in +page.svelte.
The basic problem: If you log into dexie-cloud and refresh the page, the
db.cloud.currentUser
observable never signals that the user has previously logged in. This appears to be an issue with Dexie cloud's internal state, because if you do click 'Log In' again, it magically updates the state without triggering the OTP flow.I wondered if this was SSR related, but disabling SSR with
export const ssr = false
doesn't seem to change the behaviour.