React & Firebase Auth

Firebase is a platform developed by Google that helps you build web and mobile apps. Today we’re going to take a look at using Firebase’s authentication services to add user authentication to a React app. We’ll use the Google sign-in feature, which allow users to sign in using their Google accounts. It’s one of the quickest ways to get authentication up and running in a React app. You’ll want to know how to set up a basic React app to follow along.

Project Setup

We’re going to keep things simple and try and write the least amount of code necessary to demonstrate the auth functionality. We’ll use Create React App and create a simple login/logout button in our main app component.

Ok, let’s get started by creating our app and firing it up, by typing the following in the command line:

npx create-react-app auth-tutorial
cd auth-tutorial
npm start

Nice and easy. You should now have a default app running in your browser at http://localhost:3000. Let’s go ahead and set up our Firebase project now by logging into the Firebase console. Once you’re logged in you’ll want to:

  1. Click the “Add project” button and give your project a name.
  2. Click on “Authentication” in the left sidebar menu.
  3. Click on the “Sign-in” method tab on that page, where you’ll see a list of Sign-in providers. Click the pencil on the Google option and hit the toggle to enable it.
  4. Click on the “Project Overview” in the sidebar menu.
  5. Under “Get started by adding Firebase to your app” select the “Web” option.
  6. After naming the app you should get a code snippet for adding the Firebase SDK. Go ahead and copy this, as we’ll be using it later.

Configure Firebase

There’s a node package that simplifies working with Firebase. Let’s install that now using the command line:

npm install firebase

Now, let’s create a new file in our src folder named ‘firebase.js’. This will configure our Firebase app using the npm package, and pull in only the features we need, which in this case is the auth service. We also exported the auth method and the Google sign-in provider, to be used in our main App component. You’ll need to enter the apiKey and the authDomain from the SDK info you copied above in the config object.

/src/firebase.js

import * as firebase from "firebase/app";
import "firebase/auth";

const config = {
    apiKey: "API-KEY-GOES-HERE",
    authDomain: "AUTH-DOMAIN-GOES-HERE",
};

firebase.initializeApp(config);

export const auth = firebase.auth();
export const provider = new firebase.auth.GoogleAuthProvider();

export default firebase;

Building our Component

We can now turn our attention to our main app component, where we will implement the login/logout button. Let’s import those Firebase elements and remove the default App component code:

import React, { useState } from 'react';
import { auth, provider } from './firebase.js';

function App() {
    return (
        <div className="App">
        </div>
    );
}

export default App;

We’ll need two functions: one for logging the user in and one for logging them out. Firebase will return a user object, which we’ll store in component state, using a hook. Let’s stub all that out now:

import React, { useState } from 'react';
import { auth, provider } from './firebase.js';


function App() {
    const [user, setUser] = useState(null);

    const login = () => {

    };

    const logout = () => {
        
    };

    return (
        <div className="App">
        </div>
    );
}

Our login function will call the ‘signInWithPopup’ method, available through the Firebase API, passing it our Google provider object. If it succeeds, we’ll store the returned user in our state. If it fails, we’ll log the error:

const login = () => {
    auth
    .signInWithPopup(provider)
    .then(
        function(result) {
            var user = result.user;
            setUser(user);
        }
    )
    .catch(function(error) {
        console.log(error);
    });
};

Our logout function will call the ‘signOut’ method and set our user state back to null:

const logout = () => {
    auth
    .signOut()
    .then(() => {
        setUser(null);
    });
};

Now we just need a button to call our methods. We’ll display a logout button if the user is set, and a logout button otherwise:

return (
    <div className="App">
      {user ? (
        <button onClick={logout}>Logout</button>
      ) : (
        <button onClick={login}>Login with Google</button>
      )}
    </div>
);

We should now be able to login and logout user our Google provider. Give it a try! The last thing we’ll do today is to make sure our login persists across page loads. Right now, if we reload the page we’ll be logged out again . For this, we’ll use the React effect hook to respond to the Firebase ‘onAuthStateChanged’ method, which will give us a user if we’re logged in. We’ll set our user state with that:

useEffect(() => {
    auth.onAuthStateChanged(async (user) => {
        if (user) {
            setUser(user);
        }
    });
}, []);

Wrapping Up

That’s it. We’ve covered the basics of using Firebase to get user authentication set up in a React app. Our completed component should look like this:

import React, { useState, useEffect } from 'react';
import { auth, provider } from './firebase.js';

function App() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    auth.onAuthStateChanged(async (user) => {
      if (user) {
        setUser(user);
      } 
    });
  }, []);

  const login = () => {
    auth
      .signInWithPopup(provider)
      .then(
        function (result) {
          var user = result.user;
          setUser(user);
        }
      )
      .catch(function (error) {
        console.log(error);
      });
  };

  const logout = () => {
    auth
      .signOut()
      .then(() => {
        setUser(null);
      });
  }
  
  return (
    <div className="App">
      {user ? (
        <button onClick={logout}>Logout</button>
      ) : (
        <button onClick={login}>Login with Google</button>
      )}
    </div>
  );
}

export default App;

Leave a Reply

Your email address will not be published. Required fields are marked *