Christopher Littlewood
Christopher Littlewood

Reputation: 803

ReactJS - Authenticate with React Router 4

I am new to react and I am trying to create a secure area. My app's file structure is as follows:

build
node_modules
public
src
  AboutScreen
  AdminDash
  ContactScreen
  HomeScreen
  LoginScreen
  SignUpScreen
  WorkRequestScreen
  App.js
  index.js
  routes.js
  serviceWorker.js
package.json
package-lock.json

My routing is done in App.js. This file looks like this:

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

import Home from './HomeScreen/Home';
import WorkReq from './WorkRequestScreen/WorkReq';
import About from './AboutScreen/About';
import Contact from './ContactScreen/Contact';
import Login from './LoginScreen/Login';
import Signup from './SignUpScreen/Signup';
import adminDash from './AdminDash/AdminDash';

const fakeAuth = {
  isAuthenticated: false,
  authenticate(cb) {
    this.isAuthenticated = true
    setTimeout(cb, 100)
  },
  signout(cb) {
    this.isAuthenticated = false
    setTimeout(cb, 100)
  }
}

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={(props) => (
    fakeAuth.isAuthenticated === true
      ? <Component {...props} />
      : <Redirect to={{
          pathname: '/login',
          state: { from: props.location }
        }} />
  )} />
)

class App extends Component {
  render() {
    return (
      <div>
        <PrivateRoute path='/adminDash' component={adminDash} />
        <Route exact path="/workReq" render={(props) => <WorkReq {...props}/>} />
        <Route exact path="/about" component={About}/>
        <Route exact path="/contact" component={Contact}/>
        <Route exact path="/login" component={Login}/>
        <Route exact path="/signup" component={Signup}/>
        <Route exact path="/" component={Home}/>
      </div>
    );
  }
}

export default App;

My Login component looks like this:

import App from '../App';

class LoginScreen extends Component {
  super(props);
  this.state = {
    redirectToReferrer: false,
  };

  login = () => {
    App.fakeAuth.authenticate(() => {
      this.setState(() => ({
        redirectToReferrer: true
      }))
    })
  }

  render() {

    const { from } = this.props.location.state || { from: { pathname: '/' } }
    const { redirectToReferrer } = this.state

    if (redirectToReferrer === true) {
      return <Redirect to={from} />
    }

    return (
      <div className='buttonCont'>
        <button size='lg' type='button' onClick={this.login.bind(this)}>HIT IT!</button>
      </div>
    );
  }
}

Currently this does not redirect the user to another page but will redirect them to AdminDev. The error I am getting is:

TypeError: Cannot read property 'authenticate' of undefined (login.js)

The prolem line is: App.fakeAuth.authenticate(() => {. The thing I would like to know is am I doing this right or am I missing the idea completly?

I have been following these two articles:

https://tylermcginnis.com/react-router-protected-routes-authentication/ https://auth0.com/blog/react-router-4-practical-tutorial/

Upvotes: 0

Views: 414

Answers (1)

Murli Prajapati
Murli Prajapati

Reputation: 9733

You are getting this error beacause fakeAuth is not exported from App.js file. Put the fakeAuth object into a separate file i.e. auth.js and export it from there.

// auth.js

const fakeAuth = {
  isAuthenticated: false,
  authenticate(cb) {
    this.isAuthenticated = true
    setTimeout(cb, 100)
  },
  signout(cb) {
    this.isAuthenticated = false
    setTimeout(cb, 100)
  }
}

export { fakeAuth }  

Then, import it in App.js and Login.js component like this.

import { fakeAuth } from './path-to-auth-js-file';

Upvotes: 2

Related Questions