Skip to content

Instantly share code, notes, and snippets.

@mentix02
Last active June 28, 2025 10:10
Show Gist options
  • Save mentix02/087b2fe4d58de58c03a25b378d6c672a to your computer and use it in GitHub Desktop.
Save mentix02/087b2fe4d58de58c03a25b378d6c672a to your computer and use it in GitHub Desktop.
Auth
import z from "zod";
import { createContext } from "react";
export const AuthDataSchema = z
.object({
id: z.string().optional(),
name: z.string().optional(),
email: z.string().email().optional(),
token: z.string().optional(),
})
.readonly();
export type AuthData = z.infer<typeof AuthDataSchema>;
const AuthDataContextSchema = z.object({
authData: AuthDataSchema,
isAuthenticated: z.boolean(),
logout: z.function().returns(z.void()),
login: z.function().args(AuthDataSchema).returns(z.void()),
});
export type AuthContextType = z.infer<typeof AuthDataContextSchema>;
export const EmptyAuthData: AuthData = {
id: undefined,
name: undefined,
email: undefined,
token: undefined,
};
const AuthContext = createContext<AuthContextType>({
isAuthenticated: false,
authData: EmptyAuthData,
login: () => {},
logout: () => {},
});
export default AuthContext;
import { useMemo, useCallback, useState, ReactNode } from "react";
import AuthContext, { AuthData, AuthContextType, AuthDataSchema, EmptyAuthData } from "./context";
export default function AuthProvider({ children }: { children: Readonly<ReactNode> }) {
// read from localStorage and set initial auth data
let initialAuthData: AuthData;
const localAuthData: string = localStorage.getItem("auth") || btoa("{}");
const initialAuthDataResult = AuthDataSchema.safeParse(JSON.parse(atob(localAuthData)));
if (!initialAuthDataResult.success) {
console.error("Invalid auth data in localStorage:", initialAuthDataResult.error);
localStorage.removeItem("auth");
initialAuthData = EmptyAuthData;
} else {
initialAuthData = initialAuthDataResult.data;
}
const [authData, setAuthData] = useState<AuthData>(initialAuthData);
const login = useCallback((data: AuthData) => {
setAuthData(data);
localStorage.setItem("auth", btoa(JSON.stringify(data)));
}, []);
const logout = useCallback(() => {
setAuthData({
id: undefined,
name: undefined,
email: undefined,
token: undefined,
});
}, []);
const isAuthenticated = useMemo<boolean>(() => {
return !!authData.token;
}, [authData.token]);
const contextValue = useMemo<AuthContextType>(
() => ({ authData, isAuthenticated, login, logout }),
[authData, isAuthenticated, login, logout],
);
return <AuthContext.Provider value={contextValue}>{children}</AuthContext.Provider>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment