I am building a website with SvelteKit. My auth provider is Firebase. I am trying to protect some pages with Authentication, so I am programming an auth listener in __layout.svelte
. However, no matter how I try, I can't seems to pass the Auth Status from the context module
to my script
, this is my code:
__layout.svelte
<script lang="ts" context="module">
import type { User } from 'firebase/auth';
import { onAuthStateChanged } from "firebase/auth";
import { auth } from "$lib/scripts/firebaseStart";
export async function load() {
let authUser: User|boolean = await getAuthUser();
async function getAuthUser() {
await onAuthStateChanged(auth, (user) => {
// let authUser: User|undefined;
if (user) {
// User is signed in, see docs for a list of available properties
// https://firebase.google.com/docs/reference/js/firebase.User
authUser = user;
console.log(authUser); // logs authUser out as I expected it to
// ...
} else {
// User is signed out
// ...
authUser = false;
}
});
return authUser;
}
return {
props: { authUser }
};
}
</script>
<script lang="ts">
export let authUser: User|boolean;
console.log(authUser); // logs undefined and executed before the above console log
</script>
The conclusion I get is that the code in script
tag is executed before the context=module
could return the props. How do I make the code in the context module 'blocking'?
CodePudding user response:
load
always runs before the component is created, your code is incorrect.
onAuthStateChanged
is not awaitable and returns an unsubscribe function instead. Also, you should either set the local authUser
variable or return it from the function, doing both is unnecessary/confusing.
You can turn onAuthStateChanged
into something that can be awaited by using the Promise
constructor like this:
export async function load() {
const authUser: User | boolean = await getAuthUser();
function getAuthUser() {
return new Promise(resolve => {
onAuthStateChanged(
auth,
user => resolve(user ? user : false)
);
});
}
return {
props: { authUser }
};
}
Note that onAuthStateChanged
can be called multiple times and this only captures the first change. If you want to continuously track the auth state you should update a store.