Replies: 6 comments 17 replies
-
|
In your |
Beta Was this translation helpful? Give feedback.
-
|
For // layout.ts
export const load: LayoutLoad = async function ({ data }) {
const user = data?.user // data from layout.server.ts
// rest of code
}// layout.server.ts
export const load: LayoutServerLoad = async function ({ locals }) {
// locals.user is set in hooks/index.ts
if (locals.user) {
return {
user: locals.user
}
}
} |
Beta Was this translation helpful? Give feedback.
-
|
I'm not that experienced with Sveltekit so pardon my ignorance. Since you're populating event.locals.currentUser in the login server endpoint, shouldn't you be able to access the user with event.locals in all of the layout.server.js? That's assuming all of your layouts are running on the server, not on the client. |
Beta Was this translation helpful? Give feedback.
-
|
Whenever I use invalidate with goto, I have to await - presumably to give the load functions time to rerun. /* routes/login/+page.svelte */
/* login successful */
await invalidateAll()
goto('/account') |
Beta Was this translation helpful? Give feedback.
-
|
Joy of code updated sveltekit authentication using cookies github repo. In this repo you can check the code and understand it, it's perfectly working. |
Beta Was this translation helpful? Give feedback.
-
|
Throwing this in here since it kind of related; a rough sketch/idea by Rich Harris how to get some stateful logic into client // src/lib/state.js
import { invalidate } from '$app/navigation';
import { browser } from '$app/environment';
const secret_hacky_url = '/__state';
let state = {};
export function get_state(depends) {
depends(secret_hacky_url);
return state;
}
export function set_state(new_state) {
if (!browser) {
throw new Error('cannot set state on the server');
}
state = new_state;
invalidate(secret_hacky_url);
}// src/routes/+layout.js
import { get_state } from '$lib/state.js';
/** @type {import('./$types').LayoutLoad} */
export function load({ depends }) {
const { user } = get_state(depends);
return { user };
}<!-- somewhere in the app -->
<script>
import { set_state } from '$lib/state.js';
async function login() {
const res = await fetch('/login', { method: 'POST', ... });
const user = await res.json();
set_state({ user });
}
</script>
<button on:click={login}> |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I'm trying to come up with a simple login workflow using the new routing system, but can't seem to get it to work.
Here's the high level workflow:
+layout.server.js, I get locals.currentUser and return it as "user" (assuming that then it will be available in all+layout.js)+layout.jsof the account folder, I get the user object created in the root+layout.server.jswithconst {user} = await parent()(Additionally, in
hook.jsI populateevent.locals.currentUserwith the cookie's content, so that when refreshing the browser we retrieve the user)And the problem is that in step 5, the user object is empty. I need to reload the browser for it to be populated.
Here is the code:
The login page -
routes/login/+page.svelteThe login server endpoint -
routes/api/login/+server.jsThe root layout -
routes/+layout.server.jsThe account section layout -
routes/account/+layout.jshooks.js
So, first of all, does this workflow make sense?
And if it does, why is
userempty in+layout.jsunless I refresh the browser?EDIT
Thanks to everyone who suggested a solution or a tip in the right direction.
As it turns out it's quite logical that
useris empty in/account/+layout.jsWhen I redirect from
routes/login/+page.svelte, it's all on the client side soroutes/+layout.server.jsis never called. And souseris not passed to/account/+layout.jsUsing
invalidateAll()after callinggoto(/account)will not work, because from what I understand it will re-run the load function inroutes/account/+layout.js(the active route we end up on aftergoto). So it will still not triggerroutes/+layout.server.jsSo there are two solutions:
Solution 1: create additional server pages
I can create
routes/account/+layout.server.js. From there I can get the user (it will be inlocals.currentUser), and I can pass it as a data toroutes//account/+layout.jsThis works well but I will need to add
+layout.server.js(or+page.server.js) to any route where I need the user in the load functionThat's feasible, if a little boilerplate
However in my case there's an added complication. For various reasons I am keeping only the minimum data about the user in
locals.currentUser. Then inroutes/+layout.server.jsI am loading lots of additional data about the user. This is passed to all theloadfunctions, and also set in a store on the client side.I am doing this because the user objects needs to be updated at various points in my app. With this method, I can update the client side store on the fly, and also make changes to the database. If the user refreshes the page, all the changes are retained because I am loading the full use robject in
routes/+layout.server.js. Without that, all changes would only be seen if the user logs out and back in.Solution 2: simple hack
The simple way: force a page refresh by using
location.href = "/account"instead ofgoto("account")A bit of a hack, but it works.
Conclusion:
For all the talks about making Sveltekit simpler by removing session, in practice so far it feels like a hindrance more than anything else. I basically had to recreate its functionality.
Beta Was this translation helpful? Give feedback.
All reactions