DEV Community

Haruka Kato
Haruka Kato

Posted on

Firebase Authentification using google sign-in OnAuthStateChanged logout

I was working on firebase authentification using google sign-in and a lot of articles online were explaining about Sign-in but there weren't many articles explaining logout.

It took me a while to figure this out so I want to share it here.

This is my directory structure.

So first, you sign in with google on this page.
Screen Shot 2021-01-27 at 10.30.04

Once you successfully signed in, the logout button will show up on the header. Screen Shot 2021-01-27 at 10.48.03

So, I wanted to show this logout button when a user is signed in. Here is my SignIn.js

import React, { useState } from 'react'; import 'firebase/auth' import { makeStyles } from '@material-ui/core/styles'; import Paper from '@material-ui/core/Paper'; import Grid from '@material-ui/core/Grid'; import Header from './BasicComponents/Header'; import Footer from './BasicComponents/Footer'; import Button from '@material-ui/core/Button'; import { useFirebase } from "react-redux-firebase"; import { useDispatch, useSelector } from 'react-redux'; import { push } from 'connected-react-router' const useStyles = makeStyles((theme) => ({ root: { flexGrow: 1, }, paper: { textAlign: 'center', backgroundColor: '#C0C0C0', opacity: 0.7, borderRadius: 50, height: 500, paddingTop: 20, }, grid: { position: 'block', margin: '0 auto', marginTop: 50, marginBottom: 50, }, input:{ width: '70%', height: 50, fontSize: 15, padding: '.3em', borderRadius: 10, border: '1px solid #aaa', }, input1:{ width: '70%', height: 50, fontSize: 15, padding: '.1em', marginRight: 5, borderRadius: 10, border: '1px solid #aaa', }, p1:{ textAlign: 'left', paddingLeft: 80, fontColor: 'black', }, button1:{ backgroundColor: 'pink', color: 'black', width: '35%', borderRadius:40, marginTop: 10, }, button2:{ backgroundColor: '#9400D3', color: 'black', width: '35%', borderRadius:40, }, })); export default function SignIn() { const classes = useStyles(); const auth = useSelector(state => state.auth); //global stateを呼び出すため,Dev toolをみて決めてる const dispatch = useDispatch(); const firebase = useFirebase(); const signInWithGoogle = () => { firebase .login({ provider: "google", type: "popup", }) .then(() => { dispatch({ type: "USE_PROFILE" }); dispatch(push('/top')); }); }; return ( <div className={classes.root}> <Header/> <Grid > <Grid item xs={5} className={classes.grid}> <Paper className={classes.paper}> <form> <h1>Welcome back!</h1> <p>Please sign in below to continue</p> <p className={classes.p1}>Email address</p> <input type="text" name="Email" className={classes.input1} /><br></br> <p className={classes.p1}>Password</p> <input type="password" name="password" className={classes.input} /><br></br> <Button classes={{root: classes.button1,}} type="submit"> Sign in </Button> <p>or</p> <Button classes={{root: classes.button2,}} onClick={(event) => { event.preventDefault(); signInWithGoogle(); }} > Sign in with Gmail </Button><br></br> <p >Forgot Password?</p> </form> </Paper> </Grid> </Grid> <Footer/> </div> ); } 
Enter fullscreen mode Exit fullscreen mode

And here is my index.js

import React from 'react'; import ReactDOM from 'react-dom'; import App from './App' import { Provider } from 'react-redux'; import {configureStore} from './configureStore'; import firebase from "firebase/app"; import "firebase/auth"; import "firebase/firestore"; import { useHistory } from "react-router-dom"; import { createFirestoreInstance } from "redux-firestore"; import { BrowserRouter } from "react-router-dom"; import { useDispatch, useSelector } from 'react-redux'; import { ReactReduxFirebaseProvider } from "react-redux-firebase"; import { createStore, compose } from "redux"; import { rootReducer } from "./rootReducer"; const firebaseConfig = { apiKey: "AIzaSyAOSBfTj_VQ4byWAAOWDhAsklmZtk2W_iE", authDomain: "stresstackle-599d9.firebaseapp.com", projectId: "stresstackle-599d9", storageBucket: "stresstackle-599d9.appspot.com", messagingSenderId: "930013144401", appId: "1:930013144401:web:79b25db79f4118359fdf70", measurementId: "G-J26Y6MYWV3" }; const rrfConfig = { userProfile: "users", useFirestoreForProfile: true, }; firebase.initializeApp(firebaseConfig); firebase.firestore(); export const auth = firebase.auth(); const initialState = {}; const store = createStore(rootReducer, initialState); const rrfProps = { firebase, config: rrfConfig, dispatch: store.dispatch, createFirestoreInstance, }; ReactDOM.render( <React.StrictMode> <Provider store={store}> <ReactReduxFirebaseProvider {...rrfProps}> <App /> </ReactReduxFirebaseProvider> </Provider> </React.StrictMode>, document.getElementById('root') ); 
Enter fullscreen mode Exit fullscreen mode

And App.js

import React, { Suspense } from 'react'; import { BrowserRouter as Router,Switch, Route} from 'react-router-dom'; import Top from './components/Top'; import Contact from './components/Contact'; import SignUp from './components/SignUp'; import SignIn from './components/SignIn'; import { ConnectedRouter } from 'connected-react-router'; import {history} from './configureStore'; import { Provider } from 'react-redux' import {configureStore} from './configureStore'; const store = configureStore(); const App = () => { return ( <React.Fragment> <Provider store={store}> <ConnectedRouter history={history}> <Switch> <Route exact path="/" component={Top}/> </Switch> <Switch> <Route exact path="/contact" component={Contact}/> </Switch> <Switch> <Route exact path="/signup" component={SignUp}/> </Switch> <Switch> <Route exact path="/signin" component={SignIn}/> </Switch> <Switch> <Route exact path="/top" component={Top}/> </Switch> </ConnectedRouter> </Provider> </React.Fragment> ) } export default App; 
Enter fullscreen mode Exit fullscreen mode

I use Header.js file to show the logout button.

import React from 'react' import { makeStyles } from '@material-ui/core/styles'; import AppBar from '@material-ui/core/AppBar'; import Toolbar from '@material-ui/core/Toolbar'; import Typography from '@material-ui/core/Typography'; import Button from '@material-ui/core/Button'; import {push} from "connected-react-router"; import {useDispatch, useSelector} from "react-redux"; import { useState } from 'react'; import { useEffect } from 'react' import firebase from "firebase/app"; const useStyles = makeStyles((theme) => ({ root: { flexGrow: 1, }, appBar:{ height: 90, }, button:{ fontSize:50, display: 'flex', justifyContent: 'space-between', }, })); export default function Header({children}) { const classes = useStyles(); const auth = useSelector(state => state.auth); //global stateを呼び出すため,Dev toolをみて決めてる const dispatch = useDispatch(); const [user, setUser] = useState(null); useEffect(() => { return firebase.auth().onAuthStateChanged(user => { setUser(user); }); }, []); const logout = () => { firebase .logout({ provider: "google", type: "popup", }) .then(() => { dispatch({ type: "USE_PROFILE" }); dispatch(push('/signin')); }); }; return ( <React.Fragment> <div className={classes.root}> <AppBar position="static" color='white' className={classes.appBar}> <Toolbar className={classes.button}> <p>ST</p> {user ? ( <button onClick={logout}>Google Logout</button> ) : ( <div></div> )} </Toolbar> </AppBar> </div> </React.Fragment> ); } 
Enter fullscreen mode Exit fullscreen mode

So, when a user is signed in, onAuthStateChanged changes from null. onAuthStateChanged is here to check if the state for user sign-in has changed or not.

 const [user, setUser] = useState(null); useEffect(() => { return firebase.auth().onAuthStateChanged(user => { setUser(user); }); }, []); 
Enter fullscreen mode Exit fullscreen mode

If a user signed in,

 const logout = () => { firebase .logout({ provider: "google", type: "popup", }) .then(() => { dispatch({ type: "USE_PROFILE" }); dispatch(push('/signin')); }); }; 
Enter fullscreen mode Exit fullscreen mode

This function is called and my header will show the logout button. A lot of articles I found were doing way complicated things so it took time for me to figure this out. And I felt like Firebase official document was not too helpful for the logout function.

Hope this helps!

Top comments (0)