ReactJS and Laravel - Running through a basic setup - Part 2
Tags: starter, react, laravel
Published: 2017-10-27 11:04:57

---
title: ReactJS and Laravel - Running through a basic setup - Part 2
published: true
description: Continuing our basic setup but, this time, we work on Authentication System with ReactJS and Laravel.
tags: starter,react,laravel
---

In this big article, we will use Laravel and ReactJS to setup authentication system. We'll use Auth scaffolding that comes with Laravel 5.5. Anyways, before we start running through the code, it'll be a good idea to divide our goal, the authentication system, into smaller parts:
+ Landing Page
+ Sign In Page
+ Create Account Page
+ Dashboard Page

With the idea above, we can be sure that we'll have four components: `SignInPage`, `CreateAccountPage`, `LandingPage`, `DashboardPage`. And let's say these components will be shown on `/signin`, `/account/create`, `/` and `/dashboard` URLs respectively. Considering this, we can quickly predict how our router components will look like:
```
<BrowserRouter>
    <div>
        <Route exact path="/" component={LandingPage} />
        <Route path="/signin" component={SignInPage} />
        <Route path="/account/create" component={CreateAccountPage} />
        <Route path="/dashboard" component={DashboardPage} />
    </div>
</BrowserRouter>
```
Before you ask, the `<div>` becomes necessary because `<BrowserRouter>` accepts only one child. Continuing, let's make the components:
```
const LandingPage = (props) => {
    return <div>Landing Page</div>;
};
const SignInPage = (props) => {
    return <div>Sign In Page</div>;
};
const CreateAccountPage = (props) => {
    return <div>Create Account Page</div>;
};
const DashboardPage = (props) => {
    return <div>Dashboard Page</div>;
};
```
We've kept them simple; so far. Also, notice all of the four components are stateless. It's my little thing that I always start off with stateless components and then if needed make them stateful. Unless, ofcourse, you know already that your component will have state. Anyways, we move on.


If you haven't guessed it so far, all of the code above will go into our `/resources/assets/js/components/App.js` file with a few adjustments, ofcourse. Let's see how `App.js` should look like so far:
```
import React, { Component } from 'react';
import ReactDOM from 'react-dom';

import {
    BrowserRouter,
    Route
} from 'react-router-dom';

let LandingPage = (props) => {
    return <h1 className="mt-5">Landing Page</h1>;
};
let SignInPage = (props) => {
    return <h1 className="mt-5">Sign In Page</h1>;
};
let CreateAccountPage = (props) => {
    return <h1 className="mt-5">Create Account Page</h1>;
};
let DashboardPage = (props) => {
    return <h1 className="mt-5">Dashboard Page</h1>;
};

class App extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
        <BrowserRouter>
            <div>
                <Route exact path="/" component={LandingPage} />
                <Route path="/signin" component={SignInPage} />
                <Route path="/account/create" component={CreateAccountPage} />
                <Route path="/dashboard" component={DashboardPage} />
            </div>
        </BrowserRouter>
        );
    }
};

ReactDOM.render(<App />, document.getElementById('app'));
```

And yes, by principle, `LandingPage`, `SignInPage`, `CreateAccountPage`, `DashboardPage` should be in their own file and should be imported into `App.js` but, for simplicity, we keep it as is. Next, we can make a `Header` component that contains `Link` components. So, let's import `Link` from `react-router-dom` and declare `Header` as follows:
```
let Header = (props) => {
    return (
        <nav className="navbar navbar-expand-lg navbar-light bg-light">
            <div className="container px-2 px-sm-3">
                <Link className="navbar-brand" to="/">DEV.TO</Link>
                <button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                    <span className="navbar-toggler-icon"></span>
                </button>
        
                <div className="collapse navbar-collapse" id="navbarSupportedContent">
                    <ul className="navbar-nav ml-auto">
                        <li className="nav-item">
                            <Link className="nav-link" to="/signin">Sign In</Link>
                        </li>
                        <li className="nav-item">
                            <Link className="btn btn-primary ml-lg-2 ml-sm-0 mt-2 mt-lg-0" to="/account/create">Create Account</Link>
                        </li>
                    </ul>
                    <ul className="navbar-nav ml-auto">
                        <li className="nav-item">
                            <Link className="btn btn-primary ml-lg-2 ml-sm-0 mt-2 mt-lg-0" to="/dashboard">Dashboard</Link>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    );
};
```

I have kept the Dashboard link in a separate `<ul>` because soon we will introduce a conditional `if/else` in the form of ternary operator in our Header. But, let's keep running!

I desperately want to skip to `SignInPage` component but, let's look at the `App.js` file so far:
```
import React, { Component } from 'react';
import ReactDOM from 'react-dom';

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

let LandingPage = (props) => {
    return <h1 className="mt-5">Landing Page</h1>;
};
let SignInPage = (props) => {
    return <h1 className="mt-5">Sign In Page</h1>;
};
let CreateAccountPage = (props) => {
    return <h1 className="mt-5">Create Account Page</h1>;
};
let DashboardPage = (props) => {
    return <h1 className="mt-5">Dashboard Page</h1>;
};
let Header = (props) => {
    return (
        <nav className="navbar navbar-expand-lg navbar-light bg-light">
            <div className="container px-2 px-sm-3">
                <Link className="navbar-brand" to="/">DEV.TO</Link>
                <button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
                    <span className="navbar-toggler-icon"></span>
                </button>
        
                <div className="collapse navbar-collapse" id="navbarSupportedContent">
                    <ul className="navbar-nav ml-auto">
                        <li className="nav-item">
                            <Link className="nav-link" to="/signin">Sign In</Link>
                        </li>
                        <li className="nav-item">
                            <Link className="btn btn-primary ml-lg-2 ml-sm-0 mt-2 mt-lg-0" to="/account/create">Create Account</Link>
                        </li>
                    </ul>
                    <ul className="navbar-nav ml-auto">
                        <li className="nav-item">
                            <Link className="btn btn-primary ml-lg-2 ml-sm-0 mt-2 mt-lg-0" to="/dashboard">Dashboard</Link>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    );
};

class App extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
        <BrowserRouter>
            <div>
                <Header />
                <Route exact path="/" component={LandingPage} />
                <Route path="/signin" component={SignInPage} />
                <Route path="/account/create" component={CreateAccountPage} />
                <Route path="/dashboard" component={DashboardPage} />
            </div>
        </BrowserRouter>
        );
    }
};

ReactDOM.render(<App />, document.getElementById('app'));
```

Now, `SignInPage` is going to contain a form mainly. And, for the form management, we have included `redux-form` which depends on `redux`. Let's quickly setup both:
```
...

import { createStore, combineReducers } from 'redux'
import { reducer as formReducer } from 'redux-form'

...

const rootReducer = combineReducers({
  form: formReducer,
  // my other reducers come here
});


const store = createStore(rootReducer);
```
Now, we have a Redux store but to actually use this store with React components, we'll need to use `Provider` component that comes with `react-redux` package. It's quite simple (we just need to wrap our `BrowserRouter` with `Provider` and pass the `store` as a prop) so, let's just look at our `App.js` so far:

```
import React, { Component } from 'react';
import ReactDOM from 'react-dom';

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

import { createStore, combineReducers } from 'redux'
import { reducer as formReducer } from 'redux-form'

import { Provider} from 'react-redux'

// Other components are here collapsed

const rootReducer = combineReducers({
  form: formReducer,
  // my other reducers come here
});

const store = createStore(rootReducer);

class App extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
        <Provider store={store}>
            <BrowserRouter>
                <div>
                    <Header />
                    <Route exact path="/" component={LandingPage} />
                    <Route path="/signin" component={SignInPage} />
                    <Route path="/account/create" component={CreateAccountPage} />
                    <Route path="/dashboard" component={DashboardPage} />
                </div>
            </BrowserRouter>
        </Provider>
        );
    }
};

ReactDOM.render(<App />, document.getElementById('app'));
```

Now, let's modify the `SignInPage` component:

```
class SignInPage extends Component {
    constructor(props) {
        super(props);

        this.processSubmit = this.processSubmit.bind(this);
    }

    componentWillMount() {
        // do something like setting default state
    }

    processSubmit(values) {
        // do something with the values
    }

    render() {
        const { handleSubmit, submitting } = this.props;

        return (
            <div className="container mt-5">
                <div className="row justify-content-center">
                    <div className="col-6">
                        <div className="card">
                            <div className="card-body">
                            <h2 className="text-center font-weight-light mb-4">Sign into your account</h2>
                                <form onSubmit={handleSubmit(this.processSubmit)}>
                                    <Field
                                        label="Email Address"
                                        name="email"
                                        component={FormField}
                                        id="email"
                                        type="text"
                                        className="form-control"
                                    />
                                    <Field label="Password" name="password" component={FormField} id="password" type="password" className="form-control" />
                                    <div className="form-check">
                                        <label className="form-check-label">
                                            <Field name="remember" component="input" type="checkbox" className="form-check-input mt-2" value="1" />
                                            Remember me
                                        </label>
                                    </div>
                                    <div className="form-group mt-4">
                                        <button type="submit" className="btn btn-secondary" disabled={submitting}>Continue</button>
                                    </div>
                                </form>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
};

SignInPage = reduxForm({
    form: 'signin',
    validate
})(SignInPage);
```

There a few things here to digest before we move on:
+ `SignInPage` component is no longer a pathetic dumb component that just renders  the other components and pass `props`.
+ The `reduxForm` decorator and `Field` component has been imported from `redux-form` package so, our import declaration for `redux-form` now looks like this:
```
import {
    reducer as formReducer,
    reduxForm,
    Field
} from 'redux-form'
```
+ Notice the `Field` takes a `component` as a prop. Any component that you specify will be rendered inside `Field`. The inner component that we specify gets some nice props that can be used to make the inputs interactive. Here's how I have written a basic `FormField` component:
```
const FormField = ({
        label,
        input,
        type,
        name,
        className,
        meta: { touched, error, warning }
}) => (
    <div className="form-group">
        {
            label &&
            <label htmlFor={name}>{label}</label>
        }
        <input {...input } name={name} type={type} className={
            `${className} ${
                touched && (
                    (error && 'is-invalid')
                )
            }`
        } />
        {
            touched &&
                (error && <span className="invalid-feedback">{error}</span>)
        }
    </div>
);
```
+ Look at this line carefully in the new `SignInPage` component:
```
const { handleSubmit, submitting } = this.props;
```
The `handleSubmit` and `submitting` props come from the decorated SignInPage component . `handleSubmit` takes a callback with `values` being passed as its first parameter. `submitting` is just a boolean that tells if the form is in submitting state which is helpful in disabling the submit button to prevent multiple requests when the one is being processed.

+ Also, notice `validate` property in the following lines:
```
SignInPage = reduxForm({
    form: 'signin',
    validate: validatorSignInForm,
})(SignInPage);
```
The `validate` property must hold a function that returns error messages for fields. I'll be using a simple JavaScript based validation library `validate.js` to implement `validatorSignInForm` which you can install with `npm install --save validate.js`. The validator function looks like below:

```
const validatorSignInForm = (values) => {
    const result = validate(values, {
        email: {
            presence: {
                message: '^Please enter your email address.'
            },
            email: {
                message: '^Please enter a valid email address.'
            }
        },
        password: {
            presence: {
                message: '^Please enter your password.'
            }
        }
    });

    return result;
};
```
You should know that `validate()` comes from `validate.js` library so, for now you just need to know that it takes `values` as its first argument and rules for each value in nicely formed object as its second argument.


Now, that's a lot of code that we have looked over so far but, you'll see that once you have gone through and understood  it, you'll encounter no problem creating interactive forms for your application.

Now, let's put the updated `SignInPage` component along with the code we've written in `App.js` so far and see how it looks like now:
```
import React, { Component } from 'react';
import ReactDOM from 'react-dom';

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

import { createStore, combineReducers } from 'redux'
import {
    reducer as formReducer,
    reduxForm,
    Field
} from 'redux-form'

import { Provider} from 'react-redux'

// Other components are here collapsed

const validatorSignInForm = (values) => {
    const result = validate(values, {
        email: {
            presence: {
                message: '^Please enter your email address.'
            },
            email: {
                message: '^Please enter a valid email address.'
            }
        },
        password: {
            presence: {
                message: '^Please enter your password.'
            }
        }
    });

    return result;
};

class SignInPage extends Component {
    constructor(props) {
        super(props);

        this.processSubmit = this.processSubmit.bind(this);
    }

    componentWillMount() {
        // do something like setting default state
    }

    processSubmit(values) {
        // do something with the values
    }

    render() {
        const { handleSubmit, submitting } = this.props;

        return (
            <div className="container mt-5">
                <div className="row justify-content-center">
                    <div className="col-6">
                        <div className="card">
                            <div className="card-body">
                            <h2 className="text-center font-weight-light mb-4">Sign into your account</h2>
                                <form onSubmit={handleSubmit(this.processSubmit)}>
                                    <Field
                                        label="Email Address"
                                        name="email"
                                        component={FormField}
                                        id="email"
                                        type="text"
                                        className="form-control"
                                    />
                                    <Field label="Password" name="password" component={FormField} id="password" type="password" className="form-control" />
                                    <div className="form-check">
                                        <label className="form-check-label">
                                            <Field name="remember" component="input" type="checkbox" className="form-check-input mt-2" value="1" />
                                            Remember me
                                        </label>
                                    </div>
                                    <div className="form-group mt-4">
                                        <button type="submit" className="btn btn-secondary" disabled={submitting}>Continue</button>
                                    </div>
                                </form>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        );
    }
};

SignInPage = reduxForm({
    form: 'signin',
    validate: validatorSignInForm
})(SignInPage);

const rootReducer = combineReducers({
  form: formReducer,
  // my other reducers come here
});

const store = createStore(rootReducer);

class App extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
        <Provider store={store}>
            <BrowserRouter>
                <div>
                    <Header />
                    <Route exact path="/" component={LandingPage} />
                    <Route path="/signin" component={SignInPage} />
                    <Route path="/account/create" component={CreateAccountPage} />
                    <Route path="/dashboard" component={DashboardPage} />
                </div>
            </BrowserRouter>
        </Provider>
        );
    }
};

ReactDOM.render(<App />, document.getElementById('app'));
```

# Break - Breath a little
So far, we have looked at a lot of code. You must be overwhelmed. Take a break. Inhale air. And be back where we start looking at processing the sign in form.

So, have you noticed that I had left processSubmit method of `SignInPage` component empty? Our goal will now be to look at how we will implement it. A break-down of its implementation will be:
+ Send an AJAX request to the login route with the values
+ Wait for the response
+ Do something upon the request results

Now, for sending AJAX requests, we will use `axios` - a promise based AJAX library. Don't worry, it's already installed. You can start using it like below:

```
processSubmit(values) {
    axios
    .post('/ajax/login', values)
    .then( (response) => {
        console.log(response.data);
    })
    .error( (err) => {
        console.log(err);
    });
}
```

A few things to setup before you can see the request completing successfully:
+ You need to put `Auth::routes();` in `ajax` Route group that we created in Part 1 in `/routes/web.php`.
+ You need to make sure that you have `<meta>` tag in your `web.blade.php` that contains the CSRF token otherwise, Laravel will throw TokenMismatchException instead of processing the login request. So make sure something like below is there:
```
<meta name="csrf-token" content="{{ csrf_token() }}">
```
+ By default, `AuthenticatesUsers` trait in `LoginController` has a method `sendLoginResponse` that is implemented to redirect. The problem is that we don't want to redirect instead, we want to return user details. So, copy the following lines of code and paste them as methods of `LoginController` which resides in `/app/Http/Controllers/Auth/LoginController.php`:
```
/**
 * Send the response after the user was authenticated.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Illuminate\Http\Response
 */
protected function sendLoginResponse(Request $request)
{
    $request->session()->regenerate();

    $this->clearLoginAttempts($request);

    $user = $this->guard()->user();

    if($this->authenticated($request, $user)) {
        return response()->json([
            'success' => true,
            'user' => $user
        ], 200);
    }
}

/**
 * The user has been authenticated.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  mixed  $user
 * @return mixed
 */
protected function authenticated(Request $request, $user)
{
    return true;
}
```
+ Similarly, the `AuthenticatesUsers` trait has `sendFailedLoginResponse` which also needs to be overridden. So, copy the below lines into `LoginController`:

```
/**
 * Get the failed login response instance.
 *
 * @param  \Illuminate\Http\Request  $request
 * @return \Symfony\Component\HttpFoundation\Response
 */
protected function sendFailedLoginResponse(Request $request)
{
    return response()->json([
        'success' => false,
        'message' => trans('auth.failed')
    ], 422);
}
```

Now, if you test by submitting the form, you'll be able to receive the JSON responses. Or it doesn't? Let me know.

***To be continued in Part 3. In Part 3, will continue with `processSubmit` for the `SignInPage` component. And, we will also look at how we can manage the user details using redux, prevent routes from being accessed in guest mode and much more.***

The reason I have to split this into part 3 is because the dev.to post editor has become slow due to large amount of content in it and it's annoying!