Last active
September 24, 2023 01:37
-
-
Save yinkakun/2e18bfce96487d759759f5cd48f61d3c to your computer and use it in GitHub Desktop.
next client auth with zustand, axios
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Axios from "axios"; | |
import Router from "next/router"; | |
const API_URL = process.env.NEXT_PUBLIC_API_URL; | |
export const axios = Axios.create({ | |
baseURL: API_URL, | |
headers: { | |
"Content-Type": "application/json", | |
}, | |
}); | |
axios.interceptors.response.use( | |
(response) => response, | |
(error) => { | |
if (error.response.status === 401) { | |
Router.push("/auth/login"); | |
} | |
return Promise.reject(error); | |
}, | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { axios } from "lib/axios"; | |
import { useAuthState } from "lib/store"; | |
import { Loader } from "lucide-react"; | |
import { useRouter } from "next/router"; | |
import React from "react"; | |
import { useIsClient } from "usehooks-ts"; | |
interface ProtectedRouteProps { | |
children: React.ReactNode; | |
} | |
export const ProtectedRoute = ({ children }: ProtectedRouteProps) => { | |
const router = useRouter(); | |
const isClient = useIsClient(); | |
const { authToken } = useAuthState(); | |
// if no auth token, redirect to login page | |
React.useEffect(() => { | |
if (!authToken) { | |
router.replace("/auth/login"); | |
} | |
}, [authToken]); | |
// if auth token, set axios auth header | |
React.useEffect(() => { | |
if (authToken) { | |
axios.defaults.headers.common["Authorization"] = `Bearer ${authToken}`; | |
} | |
if (!authToken) { | |
axios.defaults.headers.common["Authorization"] = undefined; | |
} | |
return () => { | |
axios.defaults.headers.common["Authorization"] = undefined; | |
}; | |
}, [authToken]); | |
if (!isClient || !authToken) | |
return ( | |
<div className="bg-app flex h-screen items-center justify-center"> | |
<Loader className="animate-spin" /> | |
</div> | |
); | |
return <React.Fragment>{children}</React.Fragment>; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { create } from "zustand"; | |
import { persist } from "zustand/middleware"; | |
interface AuthState { | |
signUpToken: string; | |
setSignUpToken: (token: string) => void; | |
userEmail: string; | |
setUserEmail: (email: string) => void; | |
authToken: string; | |
setAuthToken: (token: string) => void; | |
logOut: () => void; | |
expiresAt: number; | |
setExpiresAt: (expiresAt: number) => void; | |
} | |
export const useAuthState = create<AuthState>()( | |
persist( | |
(set) => ({ | |
signUpToken: "", | |
setSignUpToken: (token: string) => set({ signUpToken: token }), | |
userEmail: "", | |
setUserEmail: (email: string) => set({ userEmail: email }), | |
authToken: "", | |
setAuthToken: (token: string) => set({ authToken: token }), | |
logOut: () => set({ authToken: "" }), | |
expiresAt: 0, | |
setExpiresAt: (expiresAt: number) => set({ expiresAt }), | |
}), | |
{ | |
name: "pakt-dashboard", | |
}, | |
), | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment