ReactJS - Перенаправление на частный маршрут после изменения состояния - PullRequest
0 голосов
/ 02 июля 2019

Я настроил маршрут входа в Express, который при его использовании устанавливает глобальное состояние моего приложения (с использованием Context API), включая идентификатор пользователя и токен, сгенерированный JSONWebToken.

Чтобы иметь возможность загружать элементы задач для пользователя, вам необходимо иметь действительный токен, который работает, когда я отправляю его в заголовки при выполнении запроса API. Состояние также обновляется при выполнении этого с Axios, но проблема в том, что я не знаю, как (или лучший способ как) переадресовать на защищенный маршрут.

Вот мой App.js, который включает в себя маршруты для моих Welcome и Todo компонентов. Внутри Welcome есть компонент Login, который обновляет AppContext, чтобы содержать идентификатор пользователя и 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, который обновляет состояние, чтобы содержать идентификатор пользователя и токен. Взято из 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 голосов
/ 06 июля 2019

Я решил это, используя withRouter() из react-router, а затем отправил историю в Частный маршрут.

Подробнее об этом здесь: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/withRouter.md

...