Reputation: 3374
I know that session in sapper is a writable store. I can write into it in like this:
<script>
import { stores } from "@sapper/app"
const { session } = stores()
session.set("new value")
</script>
However, I have a hard time writing in inside a preload function:
<script context="module">
export async function preload(page, session) {
session = "new value" // not working, this is just a value, not a store
}
</script>
I need to set some data there during _layout.svelte
preload. Any supported way to do it?
EDIT I have ended up not using session at all, just a simple writable store. It is not that clean, but it serves the purpose. Leaving this open if someone finds the way or it becomes supported in a future.
Upvotes: 2
Views: 2687
Reputation: 306
As mentioned, the session variable in preload is not the same as your session store...they just happen to share the same name, and it works because they are isolated, by scope, from one another.
The preload function -- provided by sapper -- runs on both the client and server whereas stores -- because they are part of svelte -- exist on the client only, so importing a store into preload is not possible as far as I'm aware.
In my case, upon first visiting my app, I wanted to update the session if a session existed already for the client by using the HttpOnly cookie. The most obvious place, to me, for this code to live is the _layout.svelte file.
My workaround ended up being to create a currentSession
variable and assign it the session data like so:
<script context="module">
export async function preload(page, session) {
let currentSession = session;
return { currentSession };
}
</script>
Then, in my main script tag
<script>
export let currentSession; // <-- Needs export because it's a prop.
import { session } from '../stores.js';
session.set(currentSession);
// ...Do more stuff...
</script>
This doesn't do the ideal thing -- we both want -- which is the session variable already exists as a store with the session data upon import, but it's the next best thing I guess. The main benefit is if you initialize your stores with something like let session = writeable(null);
then $session
will not longer be null
by the time your component loads.
If you came up with a better way, please let me know. Thanks.
Upvotes: 2
Reputation: 25001
The session
param here is not the session store, it's something else. It's aluded to in the docs:
session is generated on the server by the session option passed to sapper.middleware (TODO this needs further documentation. Perhaps a server API section?)
Edit:
[ previous suggestion delete because incorrect ]
For completness: the session
is related to the session
store apparently, the argument is the value of the store. You still can't write to it in a meaningful way, though.
Like I said in comment, I don't think what you want to do is possible in preload
. Maybe I'm wrong though, someone else might tell you.
Meanwhile, I suggest the following workaround: do all this in the _layout component instance. There you'd have full access to the stores. Something like this, for example:
<script>
import { stores } from '@sapper/app'
import { resolveAuth } from './your/utils'
const { session } = stores()
resolveAuth()
.then(auth => { $session = auth })
.catch(err => { ... })
</script>
{#if $session}
<slot />
{:else}
<!-- loading indicator... or not -->
{/if}
Upvotes: 3