diff --git a/src/api/interceptors/authHeader.ts b/src/api/interceptors/authHeader.ts index 7ac8a21..afea244 100644 --- a/src/api/interceptors/authHeader.ts +++ b/src/api/interceptors/authHeader.ts @@ -1,9 +1,9 @@ import type { InternalAxiosRequestConfig } from "axios"; -import { useAuthStore } from "~/stores"; +import { authStore } from "~/stores"; export const authHeaderInterceptor = (config: InternalAxiosRequestConfig) => { - const { token } = useAuthStore.getState(); + const { token } = authStore.getState(); config.headers.Authorization = token ? `Bearer ${token}` : undefined; diff --git a/src/api/interceptors/refreshToken.ts b/src/api/interceptors/refreshToken.ts index 4bdaab1..ecb7ac8 100644 --- a/src/api/interceptors/refreshToken.ts +++ b/src/api/interceptors/refreshToken.ts @@ -1,11 +1,9 @@ import mem from "mem"; -import { useAuthStore } from "~/stores"; +import { authStore } from "~/stores"; import type { ServiceResponse } from "../api.types"; import { api } from "../axios"; -const { setToken } = useAuthStore.getState(); - export interface UserToken { refresh_token: string; token_type: string; @@ -24,13 +22,13 @@ const refreshToken = async () => { ); const { data: userToken } = response.data; if (!userToken.refresh_token) { - setToken(null); + authStore.setToken(null); } else { refreshWasSuccessful = true; - setToken(userToken.refresh_token); + authStore.setToken(userToken.refresh_token); } } catch (error) { - setToken(null); + authStore.setToken(null); } return refreshWasSuccessful; }; diff --git a/src/domains/guest/api/login.ts b/src/domains/guest/api/login.ts index d2beb66..021c991 100644 --- a/src/domains/guest/api/login.ts +++ b/src/domains/guest/api/login.ts @@ -1,6 +1,6 @@ import { api } from "~/api"; import type { ServiceResponse } from "~/api"; -import { useAuthStore } from "~/stores"; +import { authStore } from "~/stores"; export type UserToken = { accessToken: string; @@ -27,7 +27,5 @@ export const googleLogin = async ({ }; export const logout = () => { - const { setToken } = useAuthStore.getState(); - - setToken(null); + authStore.setToken(null); }; diff --git a/src/router/components/RouterWrapper/RouterWrapper.tsx b/src/router/components/RouterWrapper/RouterWrapper.tsx index 0f63535..ff2a166 100644 --- a/src/router/components/RouterWrapper/RouterWrapper.tsx +++ b/src/router/components/RouterWrapper/RouterWrapper.tsx @@ -3,14 +3,14 @@ import React from "react"; import { Navigate, Route, Routes } from "react-router-dom"; import { MainLayout } from "~/router"; -import { useAuthStore } from "~/stores"; +import { authStore } from "~/stores"; type Props = PropsWithChildren & { guest?: boolean; }; export const RouterWrapper = ({ guest = false, children }: Props) => { - const isAuthenticated = useAuthStore((state) => state.token); + const isAuthenticated = authStore.getToken(); if (!guest && !isAuthenticated) { return ; diff --git a/src/stores/index.ts b/src/stores/index.ts index fd73963..61bbc60 100644 --- a/src/stores/index.ts +++ b/src/stores/index.ts @@ -1,2 +1,2 @@ -export * from "./useAuthStore"; +export * as authStore from "./useAuthStore"; export * as exampleStore from "./useExampleStore"; diff --git a/src/stores/useAuthStore.ts b/src/stores/useAuthStore.ts index 30f21f8..bae7983 100644 --- a/src/stores/useAuthStore.ts +++ b/src/stores/useAuthStore.ts @@ -1,14 +1,8 @@ /** - * This file represents an alternative pattern when using Zustand's `persist` middleware. - * In this case, we include actions within the store itself, as `persist` handles state persistence - * across sessions. Unlike our standard approach where actions are externalized, here we centralize - * state and actions for ease of persistence management. - * * The `persist` middleware automatically saves the `token` to localStorage under the key "authStore". * We only store the `token` here to comply with HIPAA regulations, ensuring that no sensitive user information * beyond authentication tokens is persisted. * - * This pattern is specifically used when persistence is required, overriding our standard practice of separating state and actions. */ import { create } from "zustand"; @@ -16,19 +10,22 @@ import { persist } from "zustand/middleware"; export type AuthStoreState = { token: string | null; - setToken(token: string | null): void; }; -export const useAuthStore = create()( +const useAuthStore = create()( persist( - (set) => ({ + (_) => ({ token: null, - setToken: (token: string | null) => { - set(() => ({ token })); - }, }), { name: "authStore", }, ), ); + +export const getState = () => useAuthStore.getState(); + +export const getToken = () => useAuthStore((state) => state.token); + +export const setToken = (token: string | null) => + useAuthStore.setState(() => ({ token })); diff --git a/src/stores/useExampleStore.ts b/src/stores/useExampleStore.ts index 3b89870..52ce50b 100644 --- a/src/stores/useExampleStore.ts +++ b/src/stores/useExampleStore.ts @@ -1,12 +1,8 @@ /** - * This file adheres to our standard for Zustand stores without using `persist`. + * This file adheres to our standard for Zustand stores. * The state and actions are externalized, promoting modularity and separation of concerns, * as outlined in Zustand's best practices: https://zustand.docs.pmnd.rs/guides/practice-with-no-store-actions. * - * We use a namespace in the barrel file (e.g., export * as authStore from "./useAuthStore") - * to gather everything in one place, achieving both objectives: keeping concerns separate while avoiding - * multiple setters with similar names, as often seen in component states or sections. - * * This structure simplifies state management and ensures consistency across the project. */ @@ -18,17 +14,21 @@ export type ExampleStoreState = { thirdValue: number | null; }; -export const useStore = create()(() => ({ +const useStore = create(() => ({ firstValue: null, secondValue: null, thirdValue: null, })); -export const setFirstValue = () => - useStore.setState((state) => ({ firstValue: state.firstValue })); +export const getFirstValue = () => useStore((state) => state.firstValue); +export const getSecondValue = () => useStore((state) => state.secondValue); +export const getThirdValue = () => useStore((state) => state.thirdValue); + +export const setFirstValue = (firstValue: ExampleStoreState["firstValue"]) => + useStore.setState(() => ({ firstValue })); -export const setSecondValue = () => - useStore.setState((state) => ({ secondValue: state.secondValue })); +export const setSecondValue = (secondValue: ExampleStoreState["secondValue"]) => + useStore.setState(() => ({ secondValue })); -export const setThirdValue = () => - useStore.setState((state) => ({ thirdValue: state.thirdValue })); +export const setThirdValue = (thirdValue: ExampleStoreState["thirdValue"]) => + useStore.setState(() => ({ thirdValue }));