Created
February 8, 2022 03:18
-
-
Save gregfenton/f0d30ef39803f7016498ca669bf2bea0 to your computer and use it in GitHub Desktop.
A React/React-Native authentication provider that uses the Context API to make authentication & profile info available to "the rest of the app"
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 React, {createContext, useEffect, useState} from 'react'; | |
import auth from '@react-native-firebase/auth'; // or from 'firebase/auth'; | |
import Loading from '../components/Loading'; | |
import {myFirestore} from '../common/firebase.js'; | |
export const AuthContext = createContext({}); | |
export const AuthProvider = (props) => { | |
const children = props.children; | |
const [user, setUser] = useState(null); | |
const [profile, setProfile] = useState(null); | |
const [authLoading, setAuthLoading] = useState(true); | |
const loginFunction = async (email, password) => { | |
try { | |
let userCredential = await auth().signInWithEmailAndPassword(email, password); | |
let user = userCredential.user; | |
if (!user?.uid) { | |
let msg = `No UID found after signIn!`; | |
console.error(msg); | |
} | |
if (user) { | |
console.log(`Logged in as uid(${user.uid}) email(${user.email})`); | |
} | |
setUser(user); | |
} catch (ex) { | |
let msg = `Login failure for email(${email}: ${ex.message})`; | |
console.error(msg); | |
} | |
}; | |
const logoutFunction = async () => { | |
try { | |
setUser(null); // shut down the listeners | |
await auth().signOut(); | |
} catch (ex) { | |
console.error(ex); | |
} | |
}; | |
// hook into Firebase Authentication | |
useEffect(() => { | |
let unsubscribe = auth().onAuthStateChanged((user) => { | |
// if user is null, then we force them to login | |
if (user) { | |
setUser(user); | |
} | |
setAuthLoading(false); | |
}); | |
return unsubscribe; | |
}, []); | |
// listen to the user profile (FS User doc) | |
useEffect(() => { | |
const listenToUserDoc = async (uid) => { | |
let unsubscribe = await myFirestore.doc(`users/${uid}`).onSnapshot(docSnap => setProfile(docSnap.data())); | |
return unsubscribe; | |
}; | |
let unsubscribe; | |
if (user?.uid) { | |
listenToUserDoc(user.uid) | |
.then((unsub) => { | |
unsubscribe = unsub; | |
}) | |
.catch((ex) => | |
console.error(`ERROR: ActScreen useEffect: ${ex.message}`) | |
); | |
return () => { | |
unsubscribe && unsubscribe(); | |
}; | |
} else if (!user) { | |
setAuthLoading(true); | |
} | |
}, [user, setProfile]); | |
if (authLoading) { | |
return <Loading />; | |
} | |
const theValues = { | |
authLoading, | |
user, | |
profile, | |
login: loginFunction, | |
logout: logoutFunction, | |
}; | |
return ( | |
<AuthContext.Provider value={theValues}> | |
{children} | |
</AuthContext.Provider> | |
); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment