How do I use the Firebase onAuthStateChange with the new React Hooks?
You can write a Custom Hook
which registers an effect and returns the auth state
const useFirebaseAuthentication = (firebase) => {
const [authUser, setAuthUser] = useState(null);
useEffect(() =>{
const unlisten = firebase.auth.onAuthStateChanged(
authUser => {
authUser
? setAuthUser(authUser)
: setAuthUser(null);
},
);
return () => {
unlisten();
}
}, []);
return authUser
}
export default useFirebaseAuthentication;
and in any Component
you can use it like
const MyComponent = (props) => {
const firebase = useContext(FirebaseContext);
const authUser = useFirebaseAuthentication(firebase);
return (...)
}
Index.jsx
will have this code in it
ReactDOM.render(
<FirebaseProvider>
<App />
</FirebaseProvider>,
document.getElementById('root'));
This Firebase Provider is defined like this,
import Firebase from './firebase';
const FirebaseContext = createContext();
export const FirebaseProvider = (props) => (
<FirebaseContext.Provider value={new Firebase()}>
{props.children}
</FirebaseContext.Provider>
);
Related videos on Youtube
Tristan Trainer
Currently work as a full stack developer at a start up company. Working with technologies including .Net and React. Languages include C#, Javascript (+Typescript) and Ruby.
Updated on June 04, 2022Comments
-
Tristan Trainer almost 2 years
I am using
Firebase
to authenticate users for my application. I have created theSignIn
andSignUp
forms and can successfully create new users and sign in with stored users. However the issue comes with maintaining the user logged in state after aReload
.The way I have seen it done in tutorials is to use a
HOC
like the following to check if the current user is logged in.const withAuthentication = Component => { class WithAuthentication extends React.Component { constructor(props) { super(props); this.state = { authUser: null, }; } componentDidMount() { this.listener = this.props.firebase.auth.onAuthStateChanged( authUser => { authUser ? this.setState({ authUser }) : this.setState({ authUser: null }); }, ); } componentWillUnmount() { this.listener(); } render() { return ( <AuthUserContext.Provider value={this.state.authUser}> <Component {...this.props} /> </AuthUserContext.Provider> ); } } return withFirebase(WithAuthentication); }; export default withAuthentication;
However I am looking to use the new
React
Hooks
to remove the need forHOCs
. I have already removed thewithFirebase()
HOC
by using theReact Context
anduseContext(FirebaseContext)
to access a single instance ofFirebase
. Is there a way using the newhooks
to mimic thiswithAuthentication
HOC
withincomponents
that I create?I am using this tutorial
https://www.robinwieruch.de/complete-firebase-authentication-react-tutorial/
The section titled "Session Handling with Higher-Order Components" contains this part.
Thanks!
-
Jeff about 5 yearsone option is to use the react-firebase-hooks library, which has support for
onAuthStateChange
through itsuseAuthState
hook -
Tristan Trainer about 5 yearsThanks Jeff, I did look into this, however I want to reduce the number of dependencies my project has as it will have minimal maintenance in future so I don't want to have to worry too much about breaking changes!
-
Mel over 4 years@TristanTrainer - did you figure this out? I'm struggling with the same problem stackoverflow.com/questions/59977856/…
-
-
1nullpointer about 5 yearsBeginner Question , am following the same tutorial . How did you write useContext(FirebaseContext) function .Can you please share the code if possible. Also how do you apply it if it is not similar to the provided in the tutorials . Thanks
-
Shubham Khatri about 5 years@1nullpointer, useContext is a hook provided by react out of the box which you can use by importing like
import {useContext} from 'react';
-
1nullpointer about 5 yearsam trying to follow the tutorials but write the code with hooks . If am providing the context at the App level component , where do i use this code . Thats where my confusion began . : const firebase = useContext(FirebaseContext); const authUser = useFirebaseAuthentication(firebase); Or should I wrap one into another .'Provide Firebase in React' Section in the tutorials specifically
-
Shubham Khatri about 5 years@1nullpointer You will use useContext in components where you have
FirebaseContext.Consumer
in render of HOC. -
1nullpointer about 5 yearsOk, that means I need not wrap the whole render return stmt like that ? <FirebaseContext.Consumer> {firebase => { return <div>I've access to Firebase and render something.</div>; }} </FirebaseContext.Consumer>
-
Shubham Khatri about 5 yearsyes, you just need usecontext and that return you what the render prop of FirebaaseContext.Consumer returns in callback
-
1nullpointer about 5 yearsam getting Unhandled Rejection (TypeError): Firebase__WEBPACK_IMPORTED_MODULE_6_.default is not a constructor @ <FirebaseContext.Provider value={new firebase()}> Am doing import firebase from 'firebase/app' firebase.initializeApp(config) export default firebase
-
1nullpointer about 5 yearsIf I change it to <FirebaseContext.Provider value={firebase}> then i get firebase.auth.onAuthStateChanged is not a function error
-
1nullpointer about 5 yearsNever mind , got it working now by changing to firebase.auth().onAuthStateChanged() and <FirebaseContext.Provider value={firebase}>
-
1nullpointer about 5 yearsQuestion , can I merge below 2 lines so that i have a single line of code in all my consumer classes . Or does it vary based on context ? const firebase = useContext(FirebaseContext); const authUser = useFirebaseAuthentication(firebase);
-
Shubham Khatri about 5 yearsYou can craete a custom hook that calls these two hooks and returns the result, much like you did for
useFirebaseAuthentication
-
ConorLuddy almost 5 yearsThanks for this answer - it clarified a few things. FWIW, I ended up one-lining the useEffect, like so:
useEffect(() => firebase.auth.onAuthStateChanged(onChange), [])
-
Faris almost 5 years@ConorLuddy I think that might cause a memory leak because you are not closing the listener.
-
Faris over 4 yearsDoes that mean when 'onAuthStateChanged' fires, MyComponent will rerender? (the value of authUser would update)
-
ConorLuddy over 4 years@Faris - my understanding is that useEffect will run whatever method it returns, which is the un-listen from onAuthStateChanged. Open to correction though...
-
Faris over 4 years@ConorLuddy yes, I think that is the case. Thank you for your reply.
-
Mel over 4 years@ShubhamKhatri - I'm stuck with my efforts to implement your solution - do you have an advice for how to get past these config issues? stackoverflow.com/questions/59977856/… Thank you
-
Badmaash over 2 years@ShubhamKhatri Why are you not using empty brackets as dependency? You don't want to setup a listener again if state changes? Setting a listener just once is enough.
-
Shubham Khatri over 2 years@Badmaash Thank you for pointing it out. I missed it in my answer
-
metamorph_online over 2 yearsthank you!!! really appreciate your answer