title: ReactJS - Redirect to private route after state change
body: <p>I have setup a login route in Express, which when used, it will set the global state of my application (using Context API), to include the users ID and a token, generated by JSONWebToken.</p>
  
  <p>To be able to load todo items for the user, you need to have a valid token, which works when I'm sending it in the headers while doing the API request. The state is also being updated when doing this with Axios, but the problem is that I don't know how (or the best way for how) to forward to the protected route.</p>
  
  <p>Here is my App.js, which includes the routes for my <code>Welcome</code> and <code>Todo</code> components. Inside of <code>Welcome</code>, there is a <code>Login</code> component, which updates the AppContext to contain the user ID and jsonwebtoken.</p>
  
  <pre><code>import React, { useContext } from 'react'
  import { BrowserRouter as Router, Route, Redirect } from 'react-router-dom'
  import { Switch } from 'react-router'
  import TodoApp from './components/TodoApp/TodoApp'
  import Welcome from './components/Welcome/Welcome'
  import TodoProvider from './components/TodoApp/TodoContext'
  import { AppContext } from './AppContext'
  
  export default function App () {
    const context = useContext(AppContext)
  
    const PrivateRoute = ({ component: Component, ...rest }) =&gt; (
      &lt;Route
        {...rest}
        render={props =&gt;
          context.loggedIn ? &lt;Component {...props} /&gt; : &lt;Redirect to="/" /&gt;
        }
      /&gt;
    )
  
    return (
      &lt;Router&gt;
        &lt;Switch&gt;
          &lt;Route exact path="/" component={Welcome} /&gt;
          &lt;TodoProvider&gt;
            &lt;PrivateRoute exact path="/todo" component={TodoApp} /&gt;
          &lt;/TodoProvider&gt;
        &lt;/Switch&gt;
      &lt;/Router&gt;
    )
  }
  </code></pre>
  
  <p>Notice the <code>context.loggedIn</code> property it checks for, which you can see how it's changed in the last code block of this post.</p>
  
  <p>Here is my <code>Login</code> component which is inside of a simple <code>Welcome</code> component</p>
  
  <pre><code>import React, { useState, useContext } from 'react'
  import { AppContext } from '../../../AppContext'
  
  export default function Login (props) {
    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')
  
    const context = useContext(AppContext)
  
    const handleSubmit = async e =&gt; {
      e.preventDefault()
      try {
        // Method which logs in using the /api/login route, and returns users ID and token to the global state (context)
        await context.handleLogin(email, password)
      } catch {
        throw Error('Login error')
      }
    }
    return (
      &lt;form handleSubmit={handleSubmit}&gt;
        &lt;div className="input-wrapper"&gt;
          &lt;label htmlFor="email" /&gt;
          &lt;input
            type="text"
            id="login_email"
            placeholder="email"
            value={email}
            onChange={e =&gt; setEmail(e.target.value)}
          /&gt;
        &lt;/div&gt;
        &lt;div className="input-wrapper"&gt;
          &lt;label htmlFor="password" /&gt;
          &lt;input
            type="password"
            id="login_password"
            placeholder="password"
            value={password}
            onChange={e =&gt; setPassword(e.target.value)}
          /&gt;
        &lt;/div&gt;
        &lt;div className="input-wrapper"&gt;
          &lt;button
            type="submit"
            onClick={handleSubmit}
          &gt;
            Log in
          &lt;/button&gt;
        &lt;/div&gt;
      &lt;/form&gt;
    )
  }
  </code></pre>
  
  <p>And finally, the method <code>context.handleLogin</code> which updates the state to contain the users ID and token. Taken from <code>AppContext.js</code></p>
  
  <pre><code>handleLogin = (email, password) =&gt; {
    axios
      .post('http://localhost:4000/api/login/', {
        email,
        password
      })
      .then(response =&gt; {
        this.setState({
          loggedIn: response.httpStatus === 200,
          userID: response.data.data.user._id,
          token: response.data.data.token
        })
      })
      .catch(err =&gt; {
        this.setState({
          httpStatus: err.response.status,
          loginError: 'Incorrect email/password'
        })
      })
  }
  </code></pre>
  
  <p>I'm new at React, so any help would be greatly appreciated. Thanks in advance!</p>