首页 > 解决方案 > ReactJS - 状态更改后重定向到私有路由

问题描述

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

为了能够为用户加载待办事项,您需要有一个有效的令牌,当我在执行 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 的新手,所以任何帮助都将不胜感激。提前致谢!

标签: reactjsexpressauthenticationreact-routeraxios

解决方案


我通过使用withRouter()from解决了它react-router,然后将历史推送到 Private 路由。

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


推荐阅读