Search code examples
sveltegoto

Why does Svelte goto statement doesn't work on root?


Ok, so I am trying to build a simple login page with a Svelte app, for now it have almost no logic at all, but I am just trying to play a little bit with the Svelte store. But I am encountering a small problem with the goto function. So this is my file login page and it is store under routes/login

<script>
    import { goto } from "$app/navigation";
    import { isAuthenticated, login } from "./auth";

    let authenticated = false;
    isAuthenticated.subscribe(value => authenticated = value);
    $: if(authenticated) {
        console.log("here");
        goto("/");
    }
</script>

<form>
    <button on:click={() => {login("", "")}}>Login</button>
    <a href="/">test</a>
</form>

So each time I am clicking on the button I am setting the user as logged in like this :

interface User {
    email: string
}

export const isAuthenticated : Writable<boolean> = writable(false);
export const user : Writable<User> = writable<User>(undefined);
export const emptyUser : User = { email: '' };
/**
 * Function to handle the login logic of the user
 * @param email 
 * @param password 
 */
export function login(email : string, password : string) : null {
  // Call the login service on the backend and in function of
  // the result, set the user to the authenticated user


  isAuthenticated.set(true);
  user.set({ email });
  return null;
}

The if statement is executed, so it is not the problem. But I can't understand why the goto statement doesn't redirect to the root path. I even try to change the goto to a "/test" path and it worked...

I add a link to "/" to see if that would also not work, but it is working...

So I basically don't know why the goto function doesn't redirect me to the app root. If you have a solution I will gladly accept it.

Btw I already try to do it with the native way:

window.location.assign("/");

and it worked but it is not really the native way to do it in Svelte so I don't really wanna use that...


Solution

  • To start with, note that the goto function can only be called client-side. Therefore, it is recommended to check whether the code is being executed in the browser before using this function:

    $: if (typeof window !== "undefined") {
      // Your code
    }
    

    In addition, if you are using a writable store to manage authentication state, you may need to add permanent storage to persist the authentication state across different pages. To achieve this, you can change your isAuthenticated store to a persistent store using the persist function from the @macfja/svelte-persistent-store package:

    import { isAuthenticated, user, emptyUser } from "./store.js";
    
    export function logout() {
      // Perform logout logic
      // Once logged out, reset the isAuthenticated and user store values
      isAuthenticated.set(false);
      user.set(emptyUser);
    }
    

    By resetting the store values, you ensure that the authenticated variable is updated accordingly.