1

I am trying to build a simple react login app that navigates to a home page after logging in using this.props.history.push(). Unfortunately, in all of my components this.props is undefined. Here are the relevant portions:

Root:

import React from 'react'
import {
    BrowserRouter as Router,
    Route
} from 'react-router-dom'

import Login from './views/Login'
import Index from './views/Index'
import Home from './views/Home'

const App = () => {
    return(
        <Router>
            <div>
              <Route exact path="/" component={Index}/>
              <Route path="/login" component={Login}/>
              <Route path="/home" component={Home}/>
            </div>
        </Router>
    )
}

export default App

Index:

import React from 'react'
import Login from './Login'
import Home from './Home'

const Index = () => {
    if (localStorage.getItem("username")) {
        return(
            <Home/>
        );
    } else {
        return (
            <Login/>
        )
    }
}

export default Index

Login:

import React from 'react'

const Login = () => {
    let user, pass

    const login = e => {
        e.preventDefault();
        fetch("http://localhost:3000/api/login", {
            method: "GET",
            headers: {
                "user": user.value,
                "pass": pass.value
            }
        })
            .then(response => response.json())
            .then(function(data) {
                if (data.user) {
                    localStorage.setItem("username", data.user)
                    this.props.history.push("/");
                } else {
                    console.log("Failed to get user")
                }
            })
    }
    return(
      <div>
        <h1>Login</h1>
        <form onSubmit={login}>
          <label> Username:
            <input type="text" className="form-control col-md-12" ref = {node => user = node}/>
          </label>
          <label> Password:
            <input type="password" className="form-control col-md-12" ref = {node => pass = node}/>
          </label>
          <br />
          <input type="submit" value="Submit" />  
        </form>
      </div>
    )
  }

export default Login

1 Answers1

0

You also need withRouter from react-router-dom. Your login should look like this:

import React from 'react'
import { withRouter } from 'react-router-dom'

const Login = (props) => {
    let user, pass

    const login = e => {
        e.preventDefault();
        fetch("http://localhost:3000/api/login", {
            method: "GET",
            headers: {
                "user": user.value,
                "pass": pass.value
            }
        })
            .then(response => response.json())
            .then(function(data) {
                if (data.user) {
                    localStorage.setItem("username", data.user)
                    props.history.push("/");
                } else {
                    console.log("Failed to get user")
                }
            })
    }
    return(
      <div>
        <h1>Login</h1>
        <form onSubmit={login}>
          <label> Username:
            <input type="text" className="form-control col-md-12" ref = {node => user = node}/>
          </label>
          <label> Password:
            <input type="password" className="form-control col-md-12" ref = {node => pass = node}/>
          </label>
          <br />
          <input type="submit" value="Submit" />  
        </form>
      </div>
    )
  }

export default withRouter(Login)

withRouter is a higher order component. Higher order components are like wrappers that add additional functionality. They take a component as an argument and return a new component; in this case withRouter adds the history props.

Can read more about HOCs here: https://reactjs.org/docs/higher-order-components.html

Joshua Robinson
  • 2,908
  • 1
  • 22
  • 35