Site icon StartFunction

How to create a Firebase login and sign up in React

Firebase is a system that offers many platforms for devs to build web apps. One of the essential elements in an app is to create users and allow them to login. Let’s see how we can write a Firebase login that is complete yet very simple to implement.

Create your Firebase app

Install Firebase dependencies

Setup the Firebase provider

Use the Firebase login and sign up component

Setup the Firebase login and sign up

Conclusion

Create your Firebase app

You first need to create a Firebase app project so head over to the Firebase console and add a new project. You’ll add the app here.

https://console.firebase.google.com/

It will launch an assistant that will ask you the name of the project.

The next screen will ask you if you want to enable analytics. Toggle it off and click the Create project button. It will take a while to provision your project and after that, you’ll get a button to Continue that will take you to the project overview.

You now need to add a Firebase app to the Firebase project. Makes sense? A Firebase project allows you to contain several Firebase apps for iOS, Android, Web, and Unity. For now, let’s create a Web app since we’ll be using React to create our Firebase login.

You will be asked to name this app, and you’ll be given the keys that you’ll need to use to connect with Firebase. They’ll look something like:

var firebaseConfig = {
    apiKey: "1A2B3C4D5E6F7G",
    authDomain: "appname-a123b.firebaseapp.com",
    databaseURL: "https://appname-a123b.firebaseio.com",
    projectId: "appname-a123b",
    storageBucket: "appname-a123b.appspot.com",
    messagingSenderId: "1234567890",
};

We’ll use this keys in our React app to configure a provider that will allow us to access Firebase in any component under the provider.

Finally, go into Authentication in the left sidebar, the the Sign-in method tab, and enable the Email/Password authentication.

You’re all set!

Install Firebase dependencies

Firebase is available for different stacks, including JavaScript and Node.js which is what we’re going to use now. We’re going to install only two dependencies with npm:

Let’s install them with

npm i firebase reactfire

The structure of the React app will be very simple, as follows:

|-- index.js
|-- App.js
|-- FirebaseUser
    |-- index.js

and they’ll be related as follows:

index.js --import--> ./App.js --import--> ./FirebaseUser

Setup the Firebase provider

Let’s write the first file for the Firebase login and signup! We don’t actually need to write it, because this should be added to the file where you’re issuing ReactDOM.render(), in our case it will be index.js:

import { FirebaseAppProvider } from 'reactfire';

const firebaseConfig = {
    apiKey: "1A2B3C4D5E6F7G",
    authDomain: "appname-a123b.firebaseapp.com",
    databaseURL: "https://appname-a123b.firebaseio.com",
    projectId: "appname-a123b",
    storageBucket: "appname-a123b.appspot.com",
    messagingSenderId: "925199572988",
    appId: "1:123456789:web:12a34b56c78d90e"
};

This imports the FirebaseAppProvider and adds the configuration keys you’ll pass to it. You can now wrap the root component, which in our case is App with the provider:

ReactDOM.render(
  <FirebaseAppProvider firebaseConfig={ firebaseConfig }>
    <App />
  </FirebaseAppProvider>,
  document.getElementById('root')
);

Great! Now all the components below will be able to access Firebase!

Use the Firebase login and sign up component

Let’s write now the App component where we’ll import and use the FirebaseUser component to create and login a user. There’s nothing really Firebase related here. We’re going to implement a login and signup using the same component so you can see how we can reuse the code, so in this component we’ll implement a pair of buttons that when clicked, will render the FirebaseUser in a login mode or a sign up mode:

import React, { useState } from 'react';
import FirebaseUser from './FirebaseUser';

function App() {
  const [ signInOrUp, setSignInOrUp ] = useState( '' );
  return (
    <div className="App">
      <h1>Firebase login</h1>
      {
        signInOrUp ? (
          <FirebaseUser action={ signInOrUp } />
        ) : (
          <>
            <button type="button" onClick={ () => setSignInOrUp( 'signin' ) } >Log in with existing user</button>
            <button type="button" onClick={ () => setSignInOrUp( 'signup' ) } >Create a new user</button>
          </>
        )
      }
    </div>
  );
}

export default App;

Setup the Firebase login and sign up

We’ll create a component for this. We first need to import some modules:

import React, { useState } from 'react';
import { useFirebaseApp } from 'reactfire';
import 'firebase/auth';

We’ll useState for a few things, from knowing whether user is authenticated to set errors. We’re going to use the useFirebaseApp hook to access the Firebase connection. This is only possible because we setup the Firebase provider in the previous step, and it’s only available under the hierarchy where it was added. Finally, we’ll import the auth library so we can call the Firebase methods to create users and login. This is an efficient way because we’re only loading this library, and not others like firestore for the NoSQL database, or messaging for messages and notifications.

Next we’ll add a quick hook to manage our input fields:

const useField = () => {
	const [ value, setValue ] = useState( '' );
	return { value, onChange: x => setValue( 'string' === typeof x ? x : x.target.value ) };
};

And finally the full component, which we’ll break it down below to point the most interesting portions, those related to the Firebase login and signup.

function FirebaseUser ( { action = 'signin' }) {
    const email = useField();
    const password = useField();
    const [ auth, setAuth ] = useState( null );
    const [ error, setError ] = useState( '' );
    const firebase = useFirebaseApp();
    const setReceivedData = data => setAuth( data );
    const setReceivedError = error => setError( error.message );

    const signIn = e => {
        e.preventDefault();
        setError( '' );
        firebase.auth()
            .signInWithEmailAndPassword( email.value, password.value )
            .then( setReceivedData )
            .catch( setReceivedError );
    };
    
    const signUp = e => {
        e.preventDefault();
        setError( '' );
        firebase.auth()
            .createUserWithEmailAndPassword( email.value, password.value )
            .then( setReceivedData )
            .catch( setReceivedError );
    };

    const manage = 'signin' === action 
        ? {
            success: `Logged in as ${ auth?.user.email ?? '' }`,
            method: signIn,
            label: 'Sign In'
        }
        : {
            success: `Signed up as ${ auth?.user.email ?? '' }`,
            method: signUp,
            label: 'Sign Up'
        };

    return (
        <div>
            {
                auth ? (
                    <p>{ manage.success }</p>
                ) : (
                    <>
                        <form onSubmit={ manage.method }>
                            <input { ...email } placeholder="email" />
                            <input { ...password } type="password" placeholder="password" />
                            <button type="submit">{ manage.label }</button>
                            {
                                error && <p>{ error }</p>
                            }
                        </form>
                    </>
                )
            }
        </div>
    );
}

export default FirebaseUser;

First, we hook to the Firebase instance:

const firebase = useFirebaseApp();

As pointed before, this is possible because we previously wrapped the App component with the Firebase provider. Now that we’re hooked to Firebase, we can use the auth functionality and call signInWithEmailAndPassword:

const signIn = e => {
        e.preventDefault();
        setError( '' );
        firebase.auth()
            .signInWithEmailAndPassword( email.value, password.value )
            .then( setReceivedData )
            .catch( setReceivedError );
};

When it succeeds, it will set the data returned and the form fields will be replaced with

Logged in as ${ auth?.user.email ?? '' }

The data returned is a large object with very interesting properties so it’s worth adding a console.log() to our setReceivedData() function to see what else it includes.

The process to create a user is similar, except we use the function createUserWithEmailAndPassword().

Conclusion

To test our Firebase login and sign up, you can try logging in for a user that doesn’t exist so you can see the errors. After that, create a user and then log in as the user.

Demo of the Firebase login and sign up.
Fun fact: Chrome complains that the password 123456 I’m using for testing is compromised, which is true.

If you now go back to the Firebase app > Authentication > Users you’ll see the new user (you might need to use the refresh button next to Add user).

To recap, the essential steps to integrate Firebase in our React app are:

Check the GitHub repository at https://github.com/eliorivero/firebase-login-sign-up. The only difference with this one is that I’m loading the keys to configure Firebase from an .env file to avoid exposing them publicly.

If you have any questions, let me know in the comments below!

Exit mobile version