-
-
Save harrisonhenri/e46766356a32f2f24354c2634024c3ac to your computer and use it in GitHub Desktop.
AuthContext with NextJs + Nookies
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 { | |
createContext, | |
ReactNode, | |
useContext, | |
useEffect, | |
useState, | |
} from 'react' | |
import { setCookie, parseCookies, destroyCookie } from 'nookies' | |
import Router from 'next/router' | |
import { BroadcastChannel } from 'broadcast-channel' | |
import { api } from '../services/api' | |
import { success, error } from '../components/Toast' | |
type User = { | |
email: string | |
} | |
type SignInCredentials = { | |
email: string | |
password: string | |
} | |
type AuthContextData = { | |
signIn: (credentials: SignInCredentials) => Promise<void> | |
signOut: () => void | |
user?: User | |
isAuthenticated: boolean | |
} | |
type AuthProviderProps = { | |
children: ReactNode | |
} | |
const AuthContext = createContext({} as AuthContextData) | |
let authChannel: BroadcastChannel | |
export function signOut() { | |
destroyCookie(undefined, 'simon.token') | |
destroyCookie(undefined, 'simon.refreshToken') | |
authChannel.postMessage('signOut') | |
Router.push('/') | |
} | |
export function AuthProvider({ children }: AuthProviderProps) { | |
const [user, setUser] = useState<User>() | |
const isAuthenticated = !!user | |
useEffect(() => { | |
authChannel = new BroadcastChannel('auth') | |
authChannel.onmessage = (message) => { | |
switch (message.data) { | |
case 'signOut': | |
Router.push('/') | |
break | |
case 'signIn': | |
Router.push('/users') | |
break | |
default: | |
break | |
} | |
} | |
}, []) | |
useEffect(() => { | |
const { 'simon.token': token } = parseCookies() | |
if (token) { | |
api | |
.get('/users/me') | |
.then((response) => { | |
const { user } = response.data | |
setUser(user) | |
}) | |
.catch(() => { | |
signOut() | |
}) | |
} | |
}, []) | |
async function signIn({ email, password }: SignInCredentials) { | |
try { | |
const response = await api.post('/login', { | |
email, | |
pass: password, | |
}) | |
const { token } = response.data | |
setCookie(undefined, 'simon.token', token, { | |
maxAge: 60 * 60 * 24 * 30, // 30 days | |
path: '/', | |
}) | |
setUser({ | |
email, | |
}) | |
api.defaults.headers.Authorization = `Bearer ${token}` | |
Router.push('/users') | |
authChannel.postMessage('signIn') | |
success('Logado com sucesso!') | |
} catch (err) { | |
error(err.response.data.error || err.message) | |
} | |
} | |
return ( | |
<AuthContext.Provider value={{ isAuthenticated, user, signIn, signOut }}> | |
{children} | |
</AuthContext.Provider> | |
) | |
} | |
export const useAuth = () => useContext(AuthContext) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Really helpful to me! Thank you :)