Created
April 11, 2023 09:46
-
-
Save marcus-gomes-v/2900e8a052a6f5064bebac01646da721 to your computer and use it in GitHub Desktop.
Example to Use AuthContext with Firebase
This file contains hidden or 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
//LoggedIn Page | |
import { useEffect } from 'react'; | |
import { useRouter } from 'next/router'; | |
import { useAuth } from '../context/AuthUserContext'; | |
const LoggedIn = () => { | |
const { authUser, loading, signOut } = useAuth(); | |
const router = useRouter(); | |
// Listen for changes on loading and authUser, redirect if needed | |
useEffect(() => { | |
if (!loading && !authUser) | |
router.push('/') | |
}, [authUser, loading, router]) | |
return ( | |
<> | |
{ | |
loading ? | |
<div className='flex justify-center'> | |
Loading... | |
</div> : | |
<> | |
I'm Logged | |
</> | |
} | |
</> | |
) | |
} | |
export default LoggedIn; | |
// AuthUserContext | |
import { createContext, useContext } from 'react' | |
import useFirebaseAuth from '../lib/useFirebaseAuth'; | |
const authUserContext: any = createContext({ | |
authUser: {}, | |
loading: true, | |
signInWithEmailAndPassword: async () => {}, | |
createUserWithEmailAndPassword: async () => {}, | |
loginWithGoogle: async () => {}, | |
signOut: async () => {} | |
}); | |
export function AuthUserProvider({ children }: any) { | |
const auth = useFirebaseAuth(); | |
return <authUserContext.Provider value={auth}>{children}</authUserContext.Provider>; | |
} | |
export const useAuth: any = () => useContext(authUserContext); | |
//useFirebaseAuth | |
import router from 'next/router'; | |
import { useState, useEffect } from 'react' | |
import firebase from './firebase'; | |
import { iUser } from '../typings'; | |
const formatAuthUser = (user: any) => ({ | |
uid: user.uid, | |
email: user.email, | |
name: user.displayName || '', | |
imageUrl: user.photoURL || '/images/avatar/placeholder.svg', | |
code: '', | |
type: 'user', | |
teams: [] | |
}); | |
export default function useFirebaseAuth() { | |
const [authUser, setAuthUser] = useState<iUser>(); | |
const [loading, setLoading] = useState(true); | |
const authStateChanged = async (authState: any) => { | |
if (!authState) { | |
setLoading(false) | |
return; | |
} | |
setLoading(true) | |
var formattedUser: iUser = formatAuthUser(authState) as iUser; | |
setAuthUser(formattedUser); | |
setLoading(false); | |
}; | |
const clear = () => { | |
setAuthUser(undefined); | |
setLoading(true); | |
}; | |
const signInWithEmailAndPassword = (email: any, password: any) => | |
firebase.auth().signInWithEmailAndPassword(email, password); | |
const createUserWithEmailAndPassword = (email: any, password: any) => | |
firebase.auth().createUserWithEmailAndPassword(email, password); | |
const provider = new firebase.auth.GoogleAuthProvider(); | |
const loginWithGoogle = () => firebase.auth().signInWithPopup(provider) | |
const signOut = () => firebase.auth().signOut().then(() => router.push('/')).then(clear); | |
useEffect(() => { | |
const unsubscribe = firebase.auth().onAuthStateChanged(authStateChanged); | |
return () => unsubscribe(); | |
}, []); | |
return { | |
authUser, | |
loading, | |
signInWithEmailAndPassword, | |
createUserWithEmailAndPassword, | |
signOut, | |
loginWithGoogle | |
}; | |
} | |
// Page to Authenticate the User | |
import { faGoogle } from "@fortawesome/free-brands-svg-icons"; | |
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; | |
import { useState } from 'react'; | |
import { useRouter } from 'next/router'; | |
import Link from "next/link"; | |
import { useAuth } from "../../context/AuthUserContext"; | |
export default function Authentication() { | |
const { signInWithEmailAndPassword, loginWithGoogle } = useAuth(); | |
const [email, setEmail] = useState(""); | |
const [password, setPassword] = useState(""); | |
const [error, setError] = useState(null); | |
const router = useRouter(); | |
const emailAndPasswordLogin = (event: any) => { | |
setError(null) | |
signInWithEmailAndPassword(email, password) | |
.then((authUser: any) => { | |
console.log("Success. The user is created in firebase") | |
router.push('/dashboard'); | |
}) | |
.catch((error: any) => { | |
setError(error.message) | |
}); | |
event.preventDefault(); | |
}; | |
const googleLogin = (event: any) => { | |
setError(null) | |
loginWithGoogle() | |
.then((authUser: any) => { | |
console.log("Success. The user is created in firebase") | |
router.push('/dashboard'); | |
}) | |
.catch((error: any) => { | |
setError(error.message) | |
}); | |
event.preventDefault(); | |
}; | |
return ( | |
<> | |
<div className="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8"> | |
<div className="sm:mx-auto sm:w-full sm:max-w-md text-vibrant-blue-600"> | |
<div className="flex justify-center"> | |
</div> | |
<h2 className="mt-3 text-center text-3xl font-bold tracking-tight text-gray-700">Access your account</h2> | |
</div> | |
<div className="mt-8 sm:mx-auto sm:w-full sm:max-w-md"> | |
<div className="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10"> | |
<form className="space-y-6" onSubmit={emailAndPasswordLogin}> | |
{error && <>error</>} | |
<div> | |
<label htmlFor="email" className="block text-sm font-medium text-gray-700"> | |
</label> | |
<div className="mt-1"> | |
<input | |
id="email" | |
name="email" | |
type="email" | |
autoComplete="email" | |
value={email} | |
onChange={(event) => setEmail(event.target.value)} | |
required | |
className="block w-full appearance-none rounded-md border border-gray-300 px-3 py-2 placeholder-gray-400 shadow-sm focus:border-vibrant-blue-500 focus:outline-none focus:ring-vibrant-blue-500 sm:text-sm" | |
/> | |
</div> | |
</div> | |
<div> | |
<label htmlFor="password" className="block text-sm font-medium text-gray-700"> | |
Password | |
</label> | |
<div className="mt-1"> | |
<input | |
id="password" | |
name="password" | |
type="password" | |
value={password} | |
onChange={(event) => setPassword(event.target.value)} | |
autoComplete="current-password" | |
required | |
className="block w-full appearance-none rounded-md border border-gray-300 px-3 py-2 placeholder-gray-400 shadow-sm focus:border-vibrant-blue-500 focus:outline-none focus:ring-vibrant-blue-500 sm:text-sm" | |
/> | |
</div> | |
</div> | |
<div className="flex items-center justify-between"> | |
<div className="text-sm"> | |
<Link href="/sign_up"> | |
<a className="font-medium text-vibrant-blue-600 hover:text-vibrant-blue-500"> | |
Create an account | |
</a> | |
</Link> | |
</div> | |
{/* <div className="text-sm"> | |
<a href="#" className="font-medium text-vibrant-blue-600 hover:text-vibrant-blue-500"> | |
Forgot your password? | |
</a> | |
</div> */} | |
</div> | |
<div> | |
<button | |
type="submit" | |
className="flex w-full justify-center rounded-md border border-transparent bg-vibrant-blue-600 py-2 px-4 text-sm font-medium text-white shadow-sm hover:bg-vibrant-blue-700 focus:outline-none focus:ring-2 focus:ring-vibrant-blue-500 focus:ring-offset-2" | |
> | |
Login | |
</button> | |
</div> | |
</form> | |
<div className="mt-6"> | |
<div className="relative"> | |
<div className="absolute inset-0 flex items-center"> | |
<div className="w-full border-t border-gray-300" /> | |
</div> | |
<div className="relative flex justify-center text-sm"> | |
<span className="bg-white px-2 text-gray-500">Or access with</span> | |
</div> | |
</div> | |
<div className="mt-6 grid grid-cols-1 gap-3"> | |
<div> | |
<a | |
onClick={googleLogin} | |
className="inline-flex w-full justify-center rounded-md border border-gray-300 bg-white py-2 px-4 text-sm font-medium text-gray-500 shadow-sm hover:bg-gray-50" | |
> | |
<span className="inline-flex align-middle "> | |
<FontAwesomeIcon icon={faGoogle} className={`h-4 w-4 mr-3`} /> Login with Google | |
</span> | |
</a> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
</> | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment