reactjstypescriptzustand

Zustand's store not persistent


I am trying to create a frontend with zustand to manage the state of my app. But whenever i try to call the signIn method from the userStore it set the token in the store but i doesn't seems to persist when i refresh the page, however i can still find the JWT token in the "Storage" of my browser.

import { createStore } from "zustand/vanilla";
import { APIUser } from "@portail_mem_deport/common";
import { signup, signin } from "@/lib/api/auth";

interface UserStoreState {
  user: APIUser | null;
  token: string | null;
  tokenCreatedAt: number | null;
  setUser: (newUser: APIUser) => void;
  signIn: (username: string, password: string) => Promise<boolean>;
  signUp: (username: string, password: string) => Promise<boolean>;
  signOut: () => void;
  isSignIn: () => boolean;
}

export default createStore<UserStoreState>((set, get) => ({
  user: null,
  token: null,
  tokenCreatedAt: null,

  signIn: async (username, password) => {
    try {
      const resp: any = await signin(username, password);

      console.log("Resp token: ", resp.token);
      if (resp.token) {
        const now = Date.now();
        localStorage.setItem("token", resp.token);
        localStorage.setItem("tokenCreatedAt", `${now}`);
        set({
          token: resp.token,
          tokenCreatedAt: now,
        });
      }
    } catch (error) {
      console.error("Error signing in:", error);
      return false;
    }
    return true;
  },

  isSignIn: () => {
    return get().token !== null;
  },
}));

So is it the expected behaviour and if so how can i manage to keep my store updated ?

When i call the signin function :

const { signIn, token } = userStore.getState();

async function onSubmit(values: z.infer<typeof formSchema>) {
    await signIn(values.username, values.password);
    console.log("Local storage: ", localStorage.get("token"));
    console.log("Token:", token);
}

Output:

Resp token:  eyJhbGciOiJIUz.......65i1Av-c
FormLogin.tsx:30 Form Login Token:   eyJhbGciOiJIUz.......65i1Av-c

I have tried to update my store with the localstorage but it's to "dirty" :(


Solution

  • I finally found how to do it :)

    export default createStore<UserStoreState>()(
      persist(
        (set: any, get) => ({
          user: null,
          token: null,
          tokenCreatedAt: null,
    
          signIn: async (username, password) => {
            try {
              const resp: any = await signin(username, password);
    
              console.log("Resp token: ", resp.token);
              if (resp.token) {
                const now = Date.now();
                localStorage.setItem("token", resp.token);
                localStorage.setItem("tokenCreatedAt", `${now}`);
                set({
                  token: resp.token,
                  tokenCreatedAt: now,
                });
              }
            } catch (error) {
              console.error("Error signing in:", error);
              return false;
            }
            return true;
          },
          isSignIn: () => {
            return get().token !== null;
          },
        }),
        {
          name: "user-store", // name for the persist middleware
          getStorage: () => localStorage, // specify where to store the data
        }
      )
    );