ReactJS-状态更改后重定向到专用路由

时间:2019-07-02 11:57:04

标签: reactjs express authentication react-router axios

我已经在Express中设置了一个登录路由,使用该路由时,它将设置我的应用程序的全局状态(使用Context API),以包括由JSONWebToken生成的用户ID和令牌。

要能够为用户加载待办事项,您需要有一个有效的令牌,该令牌在执行API请求时在标头中发送时就可以使用。使用Axios执行此操作时,状态也会被更新,但问题是我不知道如何(或如何获得最佳方式)转发到受保护的路由。

这是我的App.js,其中包含我的WelcomeTodo组件的路由。在Welcome内部,有一个Login组件,用于更新AppContext以包含用户ID和jsonwebtoken。

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 }) => (
    <Route
      {...rest}
      render={props =>
        context.loggedIn ? <Component {...props} /> : <Redirect to="/" />
      }
    />
  )

  return (
    <Router>
      <Switch>
        <Route exact path="/" component={Welcome} />
        <TodoProvider>
          <PrivateRoute exact path="/todo" component={TodoApp} />
        </TodoProvider>
      </Switch>
    </Router>
  )
}

请注意它检查的context.loggedIn属性,您可以在本文的最后一个代码块中看到它的变化。

这是我的Login组件,位于简单的Welcome组件中

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 => {
    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 (
    <form handleSubmit={handleSubmit}>
      <div className="input-wrapper">
        <label htmlFor="email" />
        <input
          type="text"
          id="login_email"
          placeholder="email"
          value={email}
          onChange={e => setEmail(e.target.value)}
        />
      </div>
      <div className="input-wrapper">
        <label htmlFor="password" />
        <input
          type="password"
          id="login_password"
          placeholder="password"
          value={password}
          onChange={e => setPassword(e.target.value)}
        />
      </div>
      <div className="input-wrapper">
        <button
          type="submit"
          onClick={handleSubmit}
        >
          Log in
        </button>
      </div>
    </form>
  )
}

最后,方法context.handleLogin更新状态以包含用户ID和令牌。取自AppContext.js

handleLogin = (email, password) => {
  axios
    .post('http://localhost:4000/api/login/', {
      email,
      password
    })
    .then(response => {
      this.setState({
        loggedIn: response.httpStatus === 200,
        userID: response.data.data.user._id,
        token: response.data.data.token
      })
    })
    .catch(err => {
      this.setState({
        httpStatus: err.response.status,
        loginError: 'Incorrect email/password'
      })
    })
}

我是React的新手,所以我们将不胜感激。预先感谢!

1 个答案:

答案 0 :(得分:0)

我通过使用withRouter()中的react-router,然后将历史记录推到专用路线来解决了此问题。

在此处阅读有关此内容的更多信息: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/withRouter.md