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

ReactJS - Redirect to private route after state change

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

为了能够为用户加载待办事项,您需要有一个有效的令牌,当我在执行 API 请求时在 headers 中发送它时有效。使用 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 属性,您可以在 post.

的最后一个代码块中看到它是如何更改的

这是我的 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 的新手,所以非常感谢任何帮助。提前致谢!

我使用 react-router 中的 withRouter() 解决了这个问题,然后将历史推送到私有路由。

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