loading...
Cover image for Let’s Build: Workout tracker with React and Firebase part 2: authentication

Let’s Build: Workout tracker with React and Firebase part 2: authentication

sanderdebr profile image sanderdebr ・7 min read

Let’s start building our workout application!

SignIn

First, we will create a Signin component. Let start by creating the SignIn.jsx file inside /src/Pages. I’m using .jsx as extension as this indicates that this file uses JSX.

echo > SignIn.jsx

I’m using a Window machine, which creates new files with the echo command.

For our pages we will use the Material UI templates which you can find here:
https://material-ui.com/getting-started/templates/

View the source code of the sign-in-side template and copy and paste the code inside our SignIn.jsx file.

Now inside App.js import our SignIn component and replace it inside our home router:

import SignIn from './pages/SignIn';

Now the default sign in page should show up. Let’s add some basic styling.

SignIn Styling

In our config folder we will add a file called theme.config.jsx where we will declare our color palette and font settings:

For the custom Nanum Gothic font we will add the Google Fonts link inside the header of index.html:

On fonts.google.com you may find many more fonts which are free to use. Of course you can change colors in the settings document as you like.

To apply the same styling in our whole application, we need to provide a theme inside the highest components. Inside App.js we will import ThemeProvider from material UI and add this component that uses a theme variable as parameters.

We are make use of the context API of React to provide the theme through all our components inside our Router inside App.js. You can find more information here https://reactjs.org/docs/context.html

Great! Now our app should have custom colors and font.

Now we will copy the whole useStyles hook from SignIn to a seperate theme config file called /config/theme-signinup.jsx and import this file.

Also we will move the copyright component to a new file inside /components/Copyright/index.jsx and import it into SignIn.jsx.

SignIn functions

First remove the remember me checkbox. Then add a handleChange function on both TextField components for email address and password:

onchange={handleChange}

Also remove the default reload of the page by adding onto the form element a preventDefault function:

onSubmit={e => preventDefault()}

And on the Sign In button add an onClick and disabled property:

onClick={handleSubmit}
disabled={isValid}

Then we will set up an initialUser object:

const initialUser = {id: null, email: '', password: '', error null, auth: null}

and use this object as the default user inside our React Hook:

const [user, setUser = useState(initialUser()

Make sure you have useState imported:

import React, { useState } from 'react';

When the user types inside the email or password field, we will dynamically update the user object with the input:

const handleChange = e => {
const { name, value } = e.target;
setUser({...user, [name]: value})
};

First the name and value of the input gets retrieved by destructering the event.target object, then we dynamically set the object key and value of user while keeping the rest of the user object the same (using the three dots which are called the spread operator).

Let’s add an empty function handleSubmit for now, which will use the firebase class later to sign in our user.

To enable the submit button we have to check if both the email and password fields are filled in:

const isValid = user.email === '' || user.password === '';

Console.log out your user object and check if it is working correctly. SignIn component at this point:

Before we can actually verify if the user is authenticated, we have to setup Firebase and a new user has to signup onto our Firebase authentication.

Firebase

Go to firebase.google.com, create an account and add a new project which we will call “Workout Tracker”

Inside the console browse to “Authentiction” and add a new login method “Email/password”.

On the project overview page press the web icon to add a web app which we will call “workout-tracker”, skip the hosting.

Then you’ll receive the script, copy the “var firebaseConfig = { … }” object.

Create a new folder inside our components called “Firebase” with a new file “firebase.js” and copy the script inside this file.

Usually it is bad practice to keep the API key publicly in our file like we do here, but in this case it is just to identify the Firebase project. It is not a security risk.

Great! Now we will add the firebase package to our project by running:

npm install firebase

Now we will import the firebase package into our “Firebase.js” file:

import app from 'firebase/app';
import 'firebase/auth';
import 'firebase/database';

We will now create a class called “Firebase” which will hold our config, authentication and database functions inside its constructor and add methods so we can use the firebase functionalities from everywhere inside our application.

Your code now should look like this, with your own settings:

Next up we will create a so called higher order component (HOC) which basically enhances a component with anything that we would like to add to that component, in this case our Firebase class. Create a new file called context.js inside the Firebase folder.

The function above does the following:

  1. Takes in a component

  2. Keeps it properties by spreading them out {…props}

  3. Consumes Firebase by using the Context API

  4. Add the firebase class as an added property

You can read more about React HOC’s here: https://reactjs.org/docs/higher-order-components.html

And here is more information on React Context API: https://reactjs.org/docs/context.html

Create a new file called index.js inside our Firebase folder where we will import and export our firebase and context files.

Now we will provide our Firebase class inside /src/index.js file. The context API always uses a Provider and Consumer component.

Signup

Let’s copy our SignIn.jsx page into a new page called SignUp.jsx.

First we will make it possible to browse to signup from the SignIn page. Import our router functions inside SignIn.jsx

import { Link, withRouter } from 'react-router-dom';

And change the link to signup:

Don't have an account? Sign up

Into App.js import the SignUp page and add it into the route.

Now it should direct us to the SignUp page.

Let’s direct the user to the homepage when they already have an account by changing the Link again and add an extra textfield for the username.

Our initialuser object also should contain a name now and isValid should check if the name is set.

Signing up a user

First import the withFirebase function from our Firebase component

import { withFirebase } from '../components/Firebase';

Then export our page with firebase by:

export default withRouter(withFirebase(SignUp));

Now we have enhanced our SignUp component with Firebase and Router.

Add props to our SignUp function:

function SignUp(props) { ... }

and add the SignUp functionality inside handleSubmit, see the code snipper below:

  1. We have access to the Firebase props via the Higher Order Component we made.

  2. Firebase returns a promise from where we will set our user state to the initial empty user and forward the user to the dashboard page using react-router.

  3. If authUser is not returned with an error, we will keep the current state and add the error message with the spread operator.

Just before the submit button insert the error message.

Check you code with the snipper below and try to sign up a new user.

You should get an error message or redirected to /dashboard. Great, signing up is working! You can see the new user in the Firebase console authentication.

Signing in a user

Now that the user has been signed up, let’s also make sure he/she is able to sign in to our application.

We will add the preventDefault on form submit and the error message component before the submit button.

The handleSubmit functionality is also similar to the one in SignUp.jsx.

We will export our SignIn function again using withRouter() and withFirebase() which are imported into SignIn.jsx.

Check you code with the snipper below and try to login.


We already made huge progress, great job!

Next up we will add the forgot password functionality.

Forgot password

Let’s create a new component for our password forgot functionality by adding a folder PasswordForget inside components with a file Index.jsx.

We will be using the Dialog and Snackbar components from the Material UI framework. The open/close state of these items is managed by two hooks which are false (closed) by default:

const [open, setOpen] = React.useState(false)
const [openAlert, setOpenAlert] = React.useState(false)

We will also add firebase to this component so we can use the doPasswordReset function. Inside SignIn.jsx we will import the forgot password component and add it inside the grid item:

import PasswordForget from '../components/PasswordForget';

That’s better!That’s better!

Analyse the code below and add it to your project inside /src/components/PassWordForget/index.jsx

Super! We have added signing up, in and password forget functionalities by adding authentication with Firebase by using:

  • Higher order components

  • Context API

  • React Hooks

  • Firebase

  • Material UI components

In the next section we will build a custom calendar component which will hold all our workouts.

Checkout the final result: https://master.d2e0orovu8bxyk.amplifyapp.com/**
**Source code: https://github.com/sanderdebr/workout-tracker

Posted on by:

Discussion

markdown guide