Backend DevelopmentFrontend Development

Building a Blog With Reactjs And Laravel Part4: React Admin Panel

Building a Blog With Reactjs And Laravel Part4 Admin

In this part of building a simple blog with laravel and react we will focus on building the admin panel pages, and using the reactjs router to move between pages, also we will build the login page to view pages to authorized users only.

 

 

 

Installing React Router

First we need to install some dependencies like the react router, react-router-dom these two components used to setup routing, also i need to install a special npm package called dotenv and this package used to access laravel .env variables.

npm install react-router react-router-dom dotenv

Next let’s update webpack.mix.js as below:

const mix = require('laravel-mix');
require('dotenv').config();


mix.react('resources/js/admin.js', 'public/js')
   .react('resources/js/website.js', 'public/js')
   .sass('resources/sass/app.scss', 'public/css');

In the above code i loaded the .env vars using require(‘dotenv’).config(), thereby we can use process.env.<variable> to access any variable in .env.

Let’s open .env and add a new variable called MIX_APP_URL in the bottom of the file this var is the url of the project, i will use it shortly when i use the axios library to do http calls.

.env

MIX_APP_URL=http://localhost/webmobtuts/react-laravel-blog/public/

Don’t forget to run:

php artisan config:cache
php artisan config:clear

Update resources/js/bootstrap.js like this:

window._ = require('lodash');

try {
    window.Popper = require('popper.js').default;
    window.$ = window.jQuery = require('jquery');

    require('bootstrap');
} catch (e) {}


window.axios = require('axios');
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
window.axios.defaults.headers.common['Accept'] = 'application/json';
window.axios.defaults.baseURL = process.env.MIX_APP_URL + 'api';

 

Setup Routes

To make the code more clean i will add the routes in a separate component, but let’s first create the admin components for posts, categories, tags, comments, and users.

  • resources/js/admin/components/pages/Dashboard.js
  • resources/js/admin/components/pages/posts/Index.js
  • resources/js/admin/components/pages/posts/Add.js
  • resources/js/admin/components/pages/posts/Edit.js
  • resources/js/admin/components/pages/categories/Index.js
  • resources/js/admin/components/pages/categories/Add.js
  • resources/js/admin/components/pages/categories/Edit.js
  • resources/js/admin/components/pages/tags/Index.js
  • resources/js/admin/components/pages/tags/Add.js
  • resources/js/admin/components/pages/tags/Edit.js
  • resources/js/admin/components/pages/comments/Index.js
  • resources/js/admin/components/pages/users/Index.js
  • resources/js/admin/components/pages/users/Add.js
  • resources/js/admin/components/pages/users/Edit.js

 

resources/js/admin/components/pages/Dashboard.js

import React, { Component } from 'react';
import Breadcrumb from '../partials/Breadcrumb';

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

        document.body.classList.remove("login-page");
        document.body.classList.add("skin-green");
    }

    render() {
        return (
            <div className="content-wrapper">
                <section className="content-header">
                    <h1>
                        Dashboard
                        <small>Control panel</small>
                    </h1>

                    <Breadcrumb />

                </section>

                <section className="content">

                </section>
            </div>
        )
    }
}

export default Dashboard;

resources/js/admin/components/pages/posts/Index.js

import React from 'react';
import Breadcrumb from '../../partials/Breadcrumb';

class Index extends React.Component
{
    render()
    {
        return (
            <div className="content-wrapper">
                <Breadcrumb/>

                <section className="content">
                    list posts
                </section>
            </div>
        );
    }
}

export default Index;

resources/js/admin/components/pages/posts/Add.js

import React from 'react';
import Breadcrumb from '../../partials/Breadcrumb';

class Add extends React.Component
{
    render()
    {
        return (
            <div className="content-wrapper">
                <Breadcrumb/>

                <section className="content">
                    add posts
                </section>
            </div>
        );
    }
}

export default Add;

resources/js/admin/components/pages/posts/Edit.js

import React from 'react';
import Breadcrumb from '../../partials/Breadcrumb';

class Edit extends React.Component
{
    render()
    {
        return (
            <div className="content-wrapper">
                <Breadcrumb/>

                <section className="content">
                    edit posts
                </section>
            </div>
        );
    }
}

export default Edit;

resources/js/admin/components/pages/categories/Index.js

import React from 'react';
import Breadcrumb from '../../partials/Breadcrumb';

class Index extends React.Component
{
    render()
    {
        return (
            <div className="content-wrapper">
                <Breadcrumb/>

                <section className="content">
                    list categories
                </section>
            </div>
        );
    }
}

export default Index;

resources/js/admin/components/pages/categories/Add.js

import React from 'react';
import Breadcrumb from '../../partials/Breadcrumb';

class Add extends React.Component
{
    render()
    {
        return (
            <div className="content-wrapper">
                <Breadcrumb/>

                <section className="content">
                    add categories
                </section>
            </div>
        );
    }
}

export default Add;

resources/js/admin/components/pages/categories/Edit.js

import React from 'react';
import Breadcrumb from '../../partials/Breadcrumb';

class Edit extends React.Component
{
    render()
    {
        return (
            <div className="content-wrapper">
                <Breadcrumb/>

                <section className="content">
                    edit categories
                </section>
            </div>
        );
    }
}

export default Edit;

resources/js/admin/components/pages/tags/Index.js

import React from 'react';
import Breadcrumb from '../../partials/Breadcrumb';

class Index extends React.Component
{
    render()
    {
        return (
            <div className="content-wrapper">
                <Breadcrumb/>

                <section className="content">
                    list tags
                </section>
            </div>
        );
    }
}

export default Index;

resources/js/admin/components/pages/tags/Add.js

import React from 'react';
import Breadcrumb from '../../partials/Breadcrumb';

class Add extends React.Component
{
    render()
    {
        return (
            <div className="content-wrapper">
                <Breadcrumb/>

                <section className="content">
                    add tags
                </section>
            </div>
        );
    }
}

export default Add;

resources/js/admin/components/pages/tags/Edit.js

import React from 'react';
import Breadcrumb from '../../partials/Breadcrumb';

class Edit extends React.Component
{
    render()
    {
        return (
            <div className="content-wrapper">
                <Breadcrumb/>

                <section className="content">
                    edit tags
                </section>
            </div>
        );
    }
}

export default Edit;

resources/js/admin/components/pages/comments/Index.js

import React from 'react';
import Breadcrumb from '../../partials/Breadcrumb';

class Index extends React.Component
{
    render()
    {
        return (
            <div className="content-wrapper">
                <Breadcrumb/>

                <section className="content">
                    list comments
                </section>
            </div>
        );
    }
}

export default Index;

resources/js/admin/components/pages/users/Index.js

import React from 'react';
import Breadcrumb from '../../partials/Breadcrumb';

class Index extends React.Component
{
    render()
    {
        return (
            <div className="content-wrapper">
                <Breadcrumb/>

                <section className="content">
                    list users
                </section>
            </div>
        );
    }
}

export default Index;

resources/js/admin/components/pages/users/Add.js

import React from 'react';
import Breadcrumb from '../../partials/Breadcrumb';

class Add extends React.Component
{
    render()
    {
        return (
            <div className="content-wrapper">
                <Breadcrumb/>

                <section className="content">
                    add users
                </section>
            </div>
        );
    }
}

export default Add;

resources/js/admin/components/pages/users/Edit.js

import React from 'react';
import Breadcrumb from '../../partials/Breadcrumb';

class Edit extends React.Component
{
    render()
    {
        return (
            <div className="content-wrapper">
                <Breadcrumb/>

                <section className="content">
                    edit users
                </section>
            </div>
        );
    }
}

export default Edit;

resources/js/admin/components/partials/Breadcrumb.js

import React from 'react';

class Breadcrumb extends React.Component
{
    render()
    {
        return (
                <ol className="breadcrumb">
                    <li><a href="#"><i className="fa fa-dashboard"></i> Home</a></li>
                    <li className="active">Dashboard</li>
                </ol>
        )
    }
}

export default Breadcrumb;

Now create resources/js/admin/Routes.js with the following contents:

import React from 'react';
import {
    Route,
    Switch
} from 'react-router-dom';
import Dashboard from "./components/pages/Dashboard";
import ListPosts from "./components/pages/posts/Index";
import AddPosts from "./components/pages/posts/Add";
import EditPosts from "./components/pages/posts/Edit";
import ListCategories from "./components/pages/categories/Index";
import AddCategories from "./components/pages/categories/Add";
import EditCategories from "./components/pages/categories/Edit";
import ListTags from "./components/pages/tags/Index";
import AddTags from "./components/pages/tags/Add";
import EditTags from "./components/pages/tags/Edit";
import ListComments from "./components/pages/comments/Index";
import ListUsers from "./components/pages/users/Index";
import AddUsers from "./components/pages/users/Add";
import EditUsers from "./components/pages/users/Edit";

class Routes extends React.Component
{
    render()
    {
        return (
            <Switch>
                <Route exact path='/' component={Dashboard} />
                <Route exact path='/posts' component={ListPosts} />
                <Route path='/posts/add' component={AddPosts} />
                <Route path='/posts/edit/:id' component={EditPosts} />
                <Route exact path='/tags' component={ListTags} />
                <Route path='/tags/add' component={AddTags} />
                <Route path='/tags/edit/:id' component={EditTags} />
                <Route exact path='/categories' component={ListCategories} />
                <Route path='/categories/add' component={AddCategories} />
                <Route path='/categories/edit/:id' component={EditCategories} />
                <Route exact path='/comments' component={ListComments} />
                <Route exact path='/users' component={ListUsers} />
                <Route path='/users/add' component={AddUsers} />
                <Route path='/users/edit/:id' component={EditUsers} />
            </Switch>
        )
    }
}

export default Routes;

In the above code i imported Route and Switch from react-router-dom, we use the Route component to set a route to specific component, as we already did for the four components we just created above. As you see the Route takes in a path and component props.

script async src=”https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js”>

Now let’s add these routes into action so open resources/js/admin/App.js and update it as shown:

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import {
    HashRouter as Router,
    Link,
    Route,
    Switch
} from 'react-router-dom';
import Header from './components/partials/Header';
import Sidebar from './components/partials/Sidebar';
import Footer from './components/partials/Footer';
import Routes from './Routes';


class App extends Component {
    render() {
        return (
            <Router>
                    <div className="wrapper">
                        <Header/>
                        <Sidebar/>

                        <Routes/>

                        <Footer/>
                    </div>
            </Router>
        );
    }
}

export default App;

if (document.getElementById('app')) {
    ReactDOM.render(<App />, document.getElementById('app'));
}

I imported the Hash Router component then i modified the App component to enclose it with Hash Router then i added the <Routes /> component inside of it. Finally let’s add the links, this can be done in resources/js/admin/components/partials/Sidebar.js

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

const Sidebar = (props) => {

    return (
        <aside className="main-sidebar">
            <section className="sidebar">
                <div className="user-panel">
                    <div className="pull-left image">
                        <img src={process.env.MIX_APP_URL + 'assets/admin/dist/img/avatar04.png'} className="img-circle" alt="User Image" />
                    </div>
                    <div className="pull-left info">
                        <p>Admin</p>
                    </div>
                </div>
                <ul className="sidebar-menu" data-widget="tree">
                    <li className="header">MAIN NAVIGATION</li>
                    <li className={props.location.pathname=='/'?'active':''}>
                        <Link to='/'>
                            <i className="fa fa-dashboard"></i> <span>Dashboard</span>
                        </Link>
                    </li>
                    <li className={props.location.pathname=='/posts'?'active':''}>
                        <Link to='/posts'>
                            <i className="fa fa-th"></i> <span>Posts</span>
                        </Link>
                    </li>
                    <li className={props.location.pathname=='/categories'?'active':''}>
                        <Link to='/categories'>
                            <i className="fa fa-list"></i> <span>Categories</span>
                        </Link>
                    </li>
                    <li className={props.location.pathname=='/tags'?'active':''}>
                        <Link to='/tags'>
                            <i className="fa fa-tags"></i> <span>Tags</span>
                        </Link>
                    </li>
                    <li className={props.location.pathname=='/comments'?'active':''}>
                        <Link to='/comments'>
                            <i className="fa fa-comments-o"></i> <span>Comments</span>
                        </Link>
                    </li>
                    <li className={props.location.pathname=='/users'?'active':''}>
                        <Link to='/users'>
                            <i className="fa fa-users"></i> <span>Users</span>
                        </Link>
                    </li>
                </ul>
            </section>
        </aside>
    ):null;
};

export default withRouter(Sidebar);

In the above code i used the <Link /> component from the react-router-dom to replace the <a/> tag with the react link, also i imported a special component called withRouter, this is a higher order component that enable us to access route details from inside the component using props, this can be helpful for things like redirecting to another route or getting the current route pathname as you i use this to check for the current route and set “active” class.

Now run

npm run watch

Now you can navigate through the app. The next step in this article is to setup login page and connect this with the laravel login api.

 

Setting Login Page

We will add the api in separate files, and we will use axios javascript library to make ajax calls so create resources/js/admin/apis/Auth.js with the below code:

import axios from "axios";

const Auth = {
  login: (data, successCb, failCb) => {
      axios.post('/login', data).then(response => {

          successCb(response);

      }).catch(err => {

          failCb(err);
      });
  },
  logout: (successCb, failCb) => {
      axios.get('/logout', {headers: {Authorization: 'Bearer ' + localStorage.getItem("user.api_token")}})
          .then(response => {
              localStorage.clear();

              successCb(response);
          }).catch(err => {
              failCb(err);
          alert(err.response.data.message);
      });
  },
  checkAuth: (successCb, failCb) => {
      axios.get('/check-auth', {headers: {Authorization: 'Bearer ' + localStorage.getItem("user.api_token")}})
          .then(response => {
            successCb(response);
          }).catch(err => {
            failCb(err);
      });
  }
};

export default Auth;

The above object contains two functions login, logout, and checkAuth. Both functions take success callback and failure callback so that i can add custom code when using these functions in the related components.

Create component resources/js/admin/components/login/Login.js

import React, { Component } from 'react';
import { withRouter } from "react-router";
import Auth from '../../apis/Auth';

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

        document.body.classList.remove("skin-green");
        document.body.classList.add("login-page");

        this.state = {
            email: "",
            password: "",
            error_message: null,
            errors: null
        };

        this.handleSubmit = this.handleSubmit.bind(this);

        this.handleEmail = this.handleEmail.bind(this);

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

    handleEmail(e) {
        this.setState({
            email: e.target.value
        });
    }

    handlePassword(e) {
        this.setState({
            password: e.target.value
        });
    }

    handleSubmit(e) {
        e.preventDefault();

        this.setState({
            error_message: null,
            errors: null
        });

        if(this.state.email == "" || this.state.password == "") {
            this.setState({
                error_message: "Please enter login credentials"
            });

            return false;
        }

        Auth.login({email: this.state.email, password: this.state.password}, (response) => {
            if(response.data.user.is_admin == 1) {
                for (var i in response.data.user) {
                    localStorage.setItem("user." + i, response.data.user[i]);

                    setTimeout(() => {
                        this.props.history.push("/");
                    }, 500);
                }
            } else {
                localStorage.clear();

                this.setState({
                    error_message: "Unauthorized"
                });
            }
        }, (err) => {
            this.setState({
                error_message: err.response.data.message,
                errors: err.response.data.errors
            });
        });
    }

    render() {
        return (
            <div className="container">
                <div className="login-box">
                    <div className="login-logo">
                        <b>Blog</b>RL
                    </div>
                    <div className="login-box-body">
                        <p className="login-box-msg">Sign in to start your session</p>

                        {
                            this.state.error_message?(<div className="alert alert-danger">{this.state.error_message}</div>):null
                        }

                        <form action="#" method="post" onSubmit={this.handleSubmit}>
                            <div className={`form-group has-feedback ${this.state.errors && this.state.errors.email?'has-error':''}`}>
                                <input type="email" name="email" className="form-control" placeholder="Email" onChange={this.handleEmail} value={this.state.email} />
                                    <span className="glyphicon glyphicon-envelope form-control-feedback"></span>
                                {
                                    this.state.errors && this.state.errors.email?(<div className="help-block">{this.state.errors.email[0]}</div>):null
                                }
                            </div>
                            <div className={`form-group has-feedback ${this.state.errors && this.state.errors.password?'has-error':''}`}>
                                <input type="password" name="password" className="form-control" placeholder="Password" onChange={this.handlePassword} value={this.state.password} />
                                    <span className="glyphicon glyphicon-lock form-control-feedback"></span>
                                {
                                    this.state.errors && this.state.errors.password?(<div className="help-block">{this.state.errors.password[0]}</div>):null
                                }
                            </div>
                            <div className="row">
                                <div className="col-xs-4">
                                    <button type="submit" className="btn btn-primary btn-block btn-flat">Sign In</button>
                                </div>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        )
    }
}

export default withRouter(Login);

This is the login component, in the constructor i toggle body classes to use ‘login-page’ class, then is set the state. The state here contains the email, password. The error_message and errors used to store errors coming from the api in case validation error happens.

finally handleSubmit, handleEmail, and handlePassword is bound to this class, this is an essential step in order for these functions to access the state properly.

handleEmail and handlePassword is called whenever an input changes to set the state for email and password respectively. handleSubmit is used to submit the form and call the login api we just created above. In case the login succeeded we redirect the user to the dashboard else we set the error_message and errors so that it can be displayed in the form.

Denying Unauthorized Access

To apply the login we need to make an extra step, which to protect the routes for unauthorized access by redirecting the user to the login page.

To achieve this create this component resources/js/admin/AuthenticatedRoute.js

import React, { Component } from 'react';
import { Route } from 'react-router-dom';
import { Redirect, withRouter } from'react-router';

const AuthenticatedRoute = ({component: Component, ...rest}) => (
  <Route {...rest} render={props => localStorage.getItem("user.api_token")? (
      <Component {...props}/>
  ):(
      <Redirect to={{pathname: "/login", state: {from: props.location}}}/>
  )
  } />
);

export default withRouter(AuthenticatedRoute);

This component calls component dynamically by passing the component props something similar to slots in Vuejs. Then the component is displayed by checking the localStorage ‘user.api_token’ otherwise the user redirected to the login component using <Redirect /> from the ‘react-router’.

 

Update Routes

Update Routes.js by adding the Login component and applying the AuthenticatedRoute to other components.

resources/js/admin/Routes.js

import React from 'react';
import {
    HashRouter as Router,
    Link,
    Route,
    Switch
} from 'react-router-dom';
import Login from "./components/login/Login";
import AuthenticatedRoute from './AuthenticatedRoute';
import Dashboard from "./components/pages/Dashboard";
import ListPosts from "./components/pages/posts/Index";
import AddPosts from "./components/pages/posts/Add";
import EditPosts from "./components/pages/posts/Edit";
import ListCategories from "./components/pages/categories/Index";
import AddCategories from "./components/pages/categories/Add";
import EditCategories from "./components/pages/categories/Edit";
import ListTags from "./components/pages/tags/Index";
import AddTags from "./components/pages/tags/Add";
import EditTags from "./components/pages/tags/Edit";
import ListComments from "./components/pages/comments/Index";
import ListUsers from "./components/pages/users/Index";
import AddUsers from "./components/pages/users/Add";
import EditUsers from "./components/pages/users/Edit";

class Routes extends React.Component
{
    render()
    {
        return (
            <Switch>
                <Route exact path='/login' component={Login} />
                <AuthenticatedRoute exact path='/' component={Dashboard} />
                <AuthenticatedRoute exact path='/posts' component={ListPosts} />
                <AuthenticatedRoute path='/posts/add' component={AddPosts} />
                <AuthenticatedRoute path='/posts/edit/:id' component={EditPosts} />
                <AuthenticatedRoute exact path='/tags' component={ListTags} />
                <AuthenticatedRoute path='/tags/add' component={AddTags} />
                <AuthenticatedRoute path='/tags/edit/:id' component={EditTags} />
                <AuthenticatedRoute exact path='/categories' component={ListCategories} />
                <AuthenticatedRoute path='/categories/add' component={AddCategories} />
                <AuthenticatedRoute path='/categories/edit/:id' component={EditCategories} />
                <AuthenticatedRoute exact path='/comments' component={ListComments} />
                <AuthenticatedRoute exact path='/users' component={ListUsers} />
                <AuthenticatedRoute path='/users/add' component={AddUsers} />
                <AuthenticatedRoute path='/users/edit/:id' component={EditUsers} />
            </Switch>
        )
    }
}

export default Routes;

Update resources/js/admin/components/partials/Sidebar.js

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

const Sidebar = (props) => {

    return props.location.pathname != '/login'?(
        <aside className="main-sidebar">
            <section className="sidebar">
                <div className="user-panel">
                    <div className="pull-left image">
                        <img src={process.env.MIX_APP_URL + 'assets/admin/dist/img/avatar04.png'} className="img-circle" alt="User Image" />
                    </div>
                    <div className="pull-left info">
                        <p>{localStorage.getItem("user.name")}</p>
                    </div>
                </div>
                <ul className="sidebar-menu" data-widget="tree">
                    <li className="header">MAIN NAVIGATION</li>
                    <li className={props.location.pathname=='/'?'active':''}>
                        <Link to='/'>
                            <i className="fa fa-dashboard"></i> <span>Dashboard</span>
                        </Link>
                    </li>
                    <li className={props.location.pathname=='/posts'?'active':''}>
                        <Link to='/posts'>
                            <i className="fa fa-th"></i> <span>Posts</span>
                        </Link>
                    </li>
                    <li className={props.location.pathname=='/categories'?'active':''}>
                        <Link to='/categories'>
                            <i className="fa fa-list"></i> <span>Categories</span>
                        </Link>
                    </li>
                    <li className={props.location.pathname=='/tags'?'active':''}>
                        <Link to='/tags'>
                            <i className="fa fa-tags"></i> <span>Tags</span>
                        </Link>
                    </li>
                    <li className={props.location.pathname=='/comments'?'active':''}>
                        <Link to='/comments'>
                            <i className="fa fa-comments-o"></i> <span>Comments</span>
                        </Link>
                    </li>
                    <li className={props.location.pathname=='/users'?'active':''}>
                        <Link to='/users'>
                            <i className="fa fa-users"></i> <span>Users</span>
                        </Link>
                    </li>
                </ul>
            </section>
        </aside>
    ):null;
};

export default withRouter(Sidebar);

In the above code i check for if the current route is login then we hide the sidebar otherwise we display it also we display the current user name from the localStorage.

Update resources/js/admin/components/partials/Header.js

import React from 'react';
import { withRouter } from "react-router";
import Auth from '../../apis/Auth';

class Header extends React.Component {

    constructor(props)
    {
        super(props);

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

    handleLogout(e) {
        e.preventDefault();

        Auth.logout((response) => {
            this.props.history.push("/login");
        }, (err) => {
            alert(err.response.data.message);
        });
    }

    componentDidMount()
    {
        const checkauth = setInterval(() => {
            Auth.checkAuth((response) => {}, (err) => {
                clearInterval(checkauth);

                localStorage.clear();

                this.props.history.push("/login");
            });
        }, 2000);
    }

    render() {
        return this.props.location.pathname != '/login' ? (

            <header className="main-header">
                <a href="#" className="logo">
                    <span className="logo-mini"><b>B</b>RL</span>
                    <span className="logo-lg"><b>Blog</b>RL</span>
                </a>
                <nav className="navbar navbar-static-top">
                    <a href="#" className="sidebar-toggle" data-toggle="push-menu" role="button">
                        <span className="sr-only">Toggle navigation</span>
                    </a>

                    <div className="navbar-custom-menu">
                        <ul className="nav navbar-nav">

                            <li className="dropdown user user-menu">
                                <a href="#" className="dropdown-toggle" data-toggle="dropdown">
                                    <img src={process.env.MIX_APP_URL + 'assets/admin/dist/img/avatar04.png'}
                                         className="user-image" alt="User Image"/>
                                    <span className="hidden-xs">{localStorage.getItem("user.name")}</span>
                                </a>
                                <ul className="dropdown-menu">
                                    <li className="user-header">
                                        <img src={process.env.MIX_APP_URL + 'assets/admin/dist/img/avatar04.png'}
                                             className="img-circle" alt="User Image"/>

                                        <p>
                                            {localStorage.getItem("user.name")}
                                            <small>Member since {localStorage.getItem("user.created_at")}</small>
                                        </p>
                                    </li>
                                    <li className="user-footer">
                                        <div className="pull-left">
                                            <a href="#" className="btn btn-default btn-flat">Profile</a>
                                        </div>
                                        <div className="pull-right">
                                            <a href="#" onClick={this.handleLogout}
                                               className="btn btn-default btn-flat">Sign out</a>
                                        </div>
                                    </li>
                                </ul>
                            </li>
                        </ul>
                    </div>
                </nav>
            </header>
        ) : null
    }
}

export default withRouter(Header)

In the Header component i added a logout function that will be triggered when the user click the logout link. Also in the componentDidMount() hook i called the checkAuth() function using setInterval() to check if the api_token expired therefore the user is redirected to the login page.

Update resources/js/admin/components/partials/Footer.js

import React from 'react';
import { withRouter } from "react-router";

const Footer  = (props) => {
  return props.location.pathname != '/login'?(
      <footer className="main-footer">
          <strong>Copyright &copy; 2014-2016.</strong> All rights
          reserved.
      </footer>
  ):null;
};

export default withRouter(Footer);

 

 

Continue to part5: React Redux

 

3.3 3 votes
Article Rating

What's your reaction?

Excited
1
Happy
2
Not Sure
0
Confused
1

You may also like

Subscribe
Notify of
guest

12 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Haroon Niaz
Haroon Niaz
4 years ago

Hello! I am facing this error at this point “mapDispatchToProps is not defined”? Can you help to solve this? Thanks

Bikash Jha
Bikash Jha
4 years ago

Hello
Can anyone help me?
I have followed all the process from beginning but at this stage when i am loading login page i am getting bellow error http://laravelreact.com/undefinedapi/check-auth 404 (Not Found).

i have configured virtualhost on my machine.

Last edited 4 years ago by Bikash Jha
Bikash Jha
Bikash Jha
3 years ago
Reply to  WebMobTuts

Thankyou the above issue is solved.
But now i am getting
admin.js:4639 Uncaught ReferenceError: mapDispatchToProps is not defined
  at Module../resources/js/admin/components/partials/PaginationItem.js (admin.js:4639)
  at __webpack_require__ (admin.js:76511)
  at Module../resources/js/admin/components/partials/Pagination.js (admin.js:4507)
  at __webpack_require__ (admin.js:76511)
  at Module../resources/js/admin/components/pages/categories/Index.js (admin.js:3119)
  at __webpack_require__ (admin.js:76511)
  at Module../resources/js/admin/Routes.js (admin.js:2124)
  at __webpack_require__ (admin.js:76511)
  at Module../resources/js/admin/App.js (admin.js:1973)
  at __webpack_require__ (admin.js:76511)

Joe
Joe
4 years ago

Hello. I followed your tutorial to this part and I am getting this error when I go to login: GET http://public/api/check-auth (404 – Not Found) admin.js:432

Last edited 4 years ago by Joe
Joe
Joe
4 years ago
Reply to  WebMobTuts

Yes, I did set it correctly. Somehow, it stopped displaying that error and now it displays this error below in the console and doesn’t show the login page anymore.
I copied and pasted your codes step-by-step and even went back to the previous parts of your tutorial to make sure I got the same codes as yours.
Thanks.
Uncaught ReferenceError: mapDispatchToProps is not defined
  at Module../resources/js/admin/components/partials/PaginationItem.js (admin.js:75219)
  at __webpack_require__ (admin.js:20)
  at Module../resources/js/admin/components/partials/Pagination.js (admin.js:75096)
  at __webpack_require__ (admin.js:20)
  at Module../resources/js/admin/components/pages/categories/Index.js (admin.js:73516)
  at __webpack_require__ (admin.js:20)
  at Module../resources/js/admin/Routes.js (admin.js:72557)
  at __webpack_require__ (admin.js:20)
  at Module../resources/js/admin/App.js (admin.js:72425)
  at __webpack_require__ (admin.js:20)

Joe
Joe
4 years ago

Hello,
I am still getting these errors:

"http://reactlaravelproject.test:8000/public/api/check-auth" not found 

error when the login page loaded and 

"http://reactlaravelproject.test:8000/public/api/login" not found 

error when I attempt to log in.
This is what my MIX_APP_URL in the .env file looks like:

MIX_APP_URL=http://reactlaravelproject.test:8000/public/

This is from public/js/admin.js:

window.axios.defaults.baseURL = "http://reactlaravelproject.test:8000/public/" + 'api';

I followed exactly from your tutorial, but it keeps throwing this error. I would really appreciate your help. Thanks.

Last edited 4 years ago by Joe
Joe
Joe
4 years ago
Reply to  Joe

Nevermind. Disregard this comment. I solved the issue.

@kevariable
@kevariable
3 years ago

how can this is work ? /admin will payload meanwhile your routes not have /admin, i am do after open /admin url i’ll history.push(‘/’) so it’s fix the problem but after refresh it’s will back to website not admin