How to Sign a User In on the Front End
All right, welcome back to the course. In the last video we learned about local storage and authenticated requests. Specifically using this token in local storage so we can make authenticated get requests to end points like newsletters and requests.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

In this video we are going to take our log in here and get it functional completely from start to finish.

large

So right now what happens is you hit login, it's just going to reload the page and nothing happens. Now if you remember how we solved this in our sign up form it was by adding this onSubmit function and passing it into our sign up form and handling it there.

So let's go ahead and go into our signin.js and let's do the same thing, onSubmit is equal to function with fields as a parameter. And let's just say console.log trying to handle submit and then now what we need to do is go into our SigninForm here and pass this in as a parameter.

Let's put parentheses put event sorry. Let's do this let's say onSubmit is equal to some javascript here and this is where we will put the arrow function so were putting two functions. We got this onSubmit function and the one that's going in onSubmit which is going to call this function so it's kind of like two functions.

Okay so I put in an arrow function onSubmit and it calls onSubmit. And then we want to pass in event, we want to take that and throw it into a function so we can get access to our fields.

signin.js

import React, { Component } from 'react';

import SigninForm from './signinForm';

class Signin extends Componet {

  onSubmit = (fields) => {
    console.log('trying to handle submit');
  }

  render() {
    return (
      <div className='sign-in'>
        <SigninForm onSubit={(event) => this.onSubmit(event)}/>
      </div>
    )
  }
}

export default Signin;

Okay cool, now what we need to do is go into our signinForm.js. And in our signinForm. We need to go into our render function and say constant handle submit is equal to this.props so we need to take this out from redux form because this is provided and it will prevent the browser from reloading when you submit the form and it will give us access to our data. Now we need to go into a form here and just say on submit is equal to handle submit.

signinForm.js

import React, { Component } from "react";
import { reduxForm, Field } from "redux-form";

import { FormTitle } from "../formTitle";
import { FormInput, FormButton } from "../formFields";
import TextLink from "../textLink";

class SigninForm extends Component {
  render() {

    const { handleSubmit } = this.props;

    return (
      <form onSubmit={handleSubmit} className="sign-in-form">
        <FormTitle className="sign-in-form__title" text="Login" />
        <Field
          className="sign-in-form__email"
          placeholder="Enter Email"
          name="email"
          type="email"
          title="Email"
          component={FormInput}
        />
        <Field
          className="sign-in-form__password"
          placeholder="Enter Password"
          name="password"
          type="password"
          title="Password"
          component={FormInput}
        />
        <Field
          className="sign-in-form__login"
          name="login"
          type="submit"
          title="Login"
          component={FormButton}
        />
        <div className='sign-in-form__text-links'>
            <TextLink to='/forgot' text='Forgot Password'/>
            <TextLink to='/signup' text='Not a member? Register here'/>
        </div>

      </form>
    );
  }
}

SigninForm = reduxForm({
  form: "signin"
})(SigninForm);

export default SigninForm;

All right go ahead and open chrome and it should be giving us that console.log lets go ahead and sign in and you'll see it says trying to handle submit and that's exactly what we want.

large

All right now what you need to do is create an action creator that will dispatch a get request or a post request to our server to sign us in and that's going to be the signing route. All right so let's go ahead and go back to our code and let's go to our signin.js.

And we need to make that call here. So first step is connecting this to redux, so let's go up here under import react and let's say import connect in braces from react-redux and then let's go down here to our sign in and say connect two sets of parentheses and in the last one let's put in Signin.

All right cool, now what we need to do is go into our connect and pass in our actions. So if you remember connect takes a couple arguments first it takes in mapState to props which we don't need so let's put null and then it needs to take our actions.

Cool, now what we need to do is actually important actions. So let's go up here and say import star as actions from ../../actions.

signin.js

import React, { Component } from 'react';
import { connect } from 'react-redux'; 

import * as actions from '../../actions';

import SigninForm from './signinForm';

class Signin extends Component {

    onSubmit = (fields) => {
        this.props.signIn(fields, () => {
            this.props.history.push('/dashboard');
        })
    }

    render() {
        return (
            <div className='sign-in'>
                <SigninForm onSubmit={(event) => this.onSubmit(event)}/>
            </div>
        )
    }
}

export default connect(null, actions)(Signin);

All right sweet, we have our actions except we don't actually have an action to call this. We could say sign up right here but we don't want to create another sign up form we want to create a sign in form right, we want it to sign us in not create another account.

So let's go into auth.js under actions and let's write another function let's say export function signIn it takes in fields and a callback so we can navigate to the next page. So the fields are e-mail and password the success is a callback that will allow us to go back into our sign up sorry or sign in and navigate us.

It's very similar to what we have in signed up. We have a call back that will navigate us and the reason we call back is because we don't have access to this.props.history inside of our author users and that's why we have that.

OK so let's continue writing this, let's say return function dispatch and let's say axios.post and let's put some back ticks and put our root url in and let's say /signIn let's pass in our fields and let's write out our .then let's take our response, put an arrow function and say constant and what we'll do is we'll first just write these out, so the .then and then the .catch we're going to get an error back here and then we'll just say if error then console.log the error. All right cool.

auth.js

import axios from 'axios';

import { ROOT_URL } from '../config';

import { AUTHENTICATE_USER } from './types';

export function signUp(fields, success) {
    return function(dispatch) {
        axios.post(`${ROOT_URL}/signUp`, fields)
            .then(response => {
                const { token } = response.data;
                localStorage.setItem('token', token);
               dispatch({
                   type: AUTHENTICATE_USER,
                   payload: response.data
               })
               success();
            })
            .catch(err => {
                if(err) { console.log(err) }
            })
    }
}

export function signIn(fields, success) {
    return function(dispatch) {
        axios.post(`${ROOT_URL}/signIn`, fields)
            .then(response => {
                console.log(response.data);
               })
            .catch(err => {
                if(err) { console.log(err) }
            })
    }
}

So what we want to do now is just see if this is working before we do anything with our response. So lets just say console.log response.data. Now we want to do once we get this data is store the token in local storage and dispatch authenticate user to store user and set authenticated to true.

If you remember what I mean by set authenticated to true, what that means is let's go into our authReducer.js and I'll show you. You'll see we're setting this authenticated variable to true and the reason we're doing that is because on some routes we're going to make it locally not our api routes. We're going to make it so you can't view the page unless you're authenticated so that's what that is.

All right so let's go ahead and see if this is working. Let's go to our browser and I have this account on my server so it should work. Make sure you're using an account that you've created if you don't remember any of those just go and hit not a member and create an account.

Okay, I'm going to go to login and I'm going to try it. All right, looks like nothing worked, let's go back to our application. The reason it's not working is because we're not actually calling this. So let's go to signin.js. And instead of logging trying to handle submit let's say this.props.signin and let pass in our fields and a callback.

And let's just say this.props.history.push('/dashboard'); and we know this is only going to happen if we have a successful response. Now in our auth.js we're not using that success yet so this wont run this callback. Don't worry about that we just want to see if this is working, if we're getting our response.

So let's go to Google Chrome or whatever browser you're using and let's try logging in. It says this.props.signin is not a function.

large

So let's go back to our code and the reason it's not working is because we've put it in a separate file not index.js. You might be wondering yeah but sign up works and that's because in our index.js we are importing sign up from auth and exporting it in our index. So we need to do the same thing with sign in, let's put a comma and say sign in and export sign in.

index.js

import {
    signUp,
    signIn
} from './auth';

export {
    signUp,
    signIn
};

Okay cool, let's go back to Crome and let's try it, we're definitely going to get the response now. Let's hit log in and you'll see it says finished loading and we get back our token and our user.

large

So basically like the sign up except for it's signing us in.

So now what we need to do is just store it so go back to signin.js and what we need to do is basically store this token like we're doing in auth.js inside of the sign up function. So in the signIn function we want to do basically exactly what we're doing in the sign up.

So let's just copy and paste this entire localStorage thing right here and let's paste it in our export function under our console.log and over our comments.

So we're going to do the same exact thing for the backend except for it's doing it a little bit differently. The back end is checking to see if this account exists and if the password matches up. So what's going to happen is it's going to take the password and it's going to basically encrypt it and compare it to what we have encrypted on the backend, all right, it's going to decrypt that.

Okay, so let's get rid of this console log and let's try this out.

auth.js

import axios from 'axios';

import { ROOT_URL } from '../config';

import {
    AUTHENTICATE_USER
} from './types';

export function signUp(fields, success) {
    return function(dispatch) {
        axios.post(`${ROOT_URL}/signUp`, fields)
            .then(response => {
                const { token } = response.data;
                localStorage.setItem('token', token);
               dispatch({
                   type: AUTHENTICATE_USER,
                   payload: response.data
               })
               success();
            })
            .catch(err => {
                if(err) { console.log(err) }
            })
    }
}

export function signIn(fields, success) {
    return function(dispatch) {
        axios.post(`${ROOT_URL}/signIn`, fields)
            .then(response => {
                const { token } = response.data;
                localStorage.setItem('token', token);
               dispatch({
                   type: AUTHENTICATE_USER,
                   payload: response.data
               })
               success();
            })
            .catch(err => {
                if(err) { console.log(err) }
            })
    }
}

Okay, what should happen is it should go to our reducer, set authenticated to true, store the user, and navigate us to the dashboard. So let's go to Google Chrome let's get our dev tools open here and let's expand this to the right a bit.

So what should happen is it should give user value instead of empty and it should set authenticated to true, and then this whole form will basically be gone because we won't have any form on dashboard.

So let's try logging in and it looks like it did just that form is empty, AUTH has user with an object with all of our information here, passwords encrypted, admins false, email, unit number, full name, and ID. Authenticated is false, so let's go and make sure that we are setting that true because for some reason it's false.

So what we need to do is go into our index.js and go into our authreducer so that will take us to our authReducer.js and what we want to do is basically just say ...state, user and right above that right above user let's say authenticated is true.

authReducer.js

import {
    AUTHENTICATE_USER
} from '../actions/types';

const INITIAL_STATE = {
    authenticated: false,
    user: []
}

export default function(state = INITIAL_STATE, action) {
    switch (action.type) {
        case AUTHENTICATE_USER:
            const { user } = action.payload;
            return {
                ...state,
                authenticated: true,
                user
            }
        default: return state;
    }
}

Okay, that should be setting it all good. Let's go back to our browser and we should be seeing that now. So I'm going to go to localhost:3000 and thats going to take us to our sign in page.

Give our forms some values fill those out and then hit log and that should get rid of our form values and set authenticated to true and give user seven values. All right, give user our values and authenticated it is true and form is empty, so that's what we want.

All right so now we have sign in and sign up completely functional. What I want to do in the next video is show you how we can basically protect dashboard. We only want to show the user dashboard we only want this route accessible if authenticated is true and we're going to learn how to do that by using a high order component we're going to build and we're going to call it authenticate user, all right.

So let's go ahead and commit our code.

Terminal

git status
git add .
git commit -m "built signin functionality"

OK see you in the next video.

Resources

Source code