Значения не передаются должным образом в функцию - PullRequest
0 голосов
/ 03 декабря 2018

Я относительно новичок, чтобы реагировать, так что это может быть простой вопрос.И заранее прошу прощения, если название не точное.

Я пытаюсь сделать защищенный маршрут с реакции-маршрутизатор-дом.Я думал, что у меня правильный код, но по какой-то причине, вероятно, ошибка ID-10-T с моей стороны, когда пользователь вошел в систему и вызвал PrivateRoute, информация об аутентификации не передается правильно.Ниже приведен мой код и фрагмент журнала консоли при попадании на / dashboard route.

import React, { Component } from 'react';
import axios from 'axios'

import {
  BrowserRouter as Router,
  Route,
  Redirect,
  Switch
} from "react-router-dom";

import './App.css';

import Dashboard from "./pages/Dashboard";
import Home from "./pages/Home";
import NoMatch from "./pages/NoMatch";
import Signin from "./pages/Signin";
import Signup from "./pages/Signup";

class App extends Component {
  constructor(props) {
    super()
    this.state = {
      isAuthenticated: null,
      loggedIn: false,
      username: null
    }

    this.getUser = this.getUser.bind(this)
    this.componentWillMount = this.componentWillMount.bind(this)
  }

  componentWillMount() {
    this.getUser()
  }

  getUser() {
    axios.get('/api/auth/user')
      .then(res => {
        console.log('Get user response: ')
        console.log(res.data)
        if (res.data.user) {
          console.log('Get User: There is a user saved in the server session: ')
          console.log(res.data.user)
          this.setState({
            isAuthenticated: true,
            loggedIn: true,
            username: res.data.user.username
          })
          console.log("this.state.isAuthenticated value:")
          console.log(this.state.isAuthenticated)
        } else {
          console.log('Get user: no user');
          this.setState({
            isAuthenticated: false,
            loggedIn: false,
            username: null
          })
          console.log("this.state.isAuthenticated value:")
          console.log(this.state.isAuthenticated)
        }
      })
      .catch((err) => {
        console.log('Error fetching authorized user.');
        console.log(err)
      });
  }

  render() {
    return (
      <div>
        <Router>
          <div>
            <Switch>
              <Route exact path="/" component={Home} />
              <Route exact path="/signin" component={Signin} />
              <Route exact path="/signup" component={Signup} />
              <PrivateRoute
                authed={this.state.isAuthenticated}
                path="/dashboard"
                component={Dashboard} />
              <Route component={NoMatch} />
            </Switch>
          </div>
        </Router>
      </div>
    )
  }

}

function PrivateRoute({ component: Component, authed, ...rest }) {
  console.log("PrivateRoute")
  console.log("authed value:")
  console.log(authed)
  return (
    <Route
      {...rest}
      render={(props) => (authed === true)
        ? (<Component {...props} />)
        : (<Redirect
          to={{
            pathname: '/signin',
            state: { from: props.location }
          }}
        />)}
    />
  )
}

export default App;

Вывод на консоль:

PrivateRoute
authed value:
null
Get user response: 
{user: {…}}
Get User: There is a user saved in the server session: 
{id: 1, firstname: "xxxx", lastname: "xxxx", username: "xxxx", email: "xxxx@xxxx.com", …}
this.state.isAuthenticated value:
true

Похоже, что PrivateRoute обрабатывается перед componentWillMount, но я не уверен, как это предотвратить.

Любая помощьбыл бы признателен.

1 Ответ

0 голосов
/ 03 декабря 2018

В вашем коде есть несколько вещей, к которым вам может понадобиться обратиться.

  1. Вам не нужно связывать componentWillMount или любой метод жизненного цикла.
  2. Изменить *От 1007 * до componentDidMount.Хорошей практикой является выполнение вызовов API после того, как компонент в смонтированном виде componentWillMount будет вызван до монтирования компонента App.
  3. PrivateRoute будет вызван только тогда, когда метод рендеринга компонента Appвызывается.Но поскольку все вызовы API являются асинхронными, метод рендеринга компонента App будет вызываться даже до успешного вызова API, поскольку все вызовы API являются асинхронными в JavaScript.И когда вызов API завершится успешно, состояние будет обновлено, и компонент App будет повторно визуализирован с обновленным состоянием.

Вот обновленный код, относящийся к пунктам, упомянутым выше.

class App extends Component {
  constructor(props) {
    super()
    this.state = {
      isAuthenticated: false, // change null to false
      loggedIn: false,
      username: null
    }

    this.getUser = this.getUser.bind(this)
    // this.componentWillMount = this.componentWillMount.bind(this)
  }

  componentDidMount() {
    this.getUser()
  }

  getUser() {
    axios.get('/api/auth/user')
      .then(res => {
        console.log('Get user response: ')
        console.log(res.data)
        if (res.data.user) {
          console.log('Get User: There is a user saved in the server session: ')
          console.log(res.data.user)
          this.setState({
            isAuthenticated: true,
            loggedIn: true,
            username: res.data.user.username
          })
          console.log("this.state.isAuthenticated value:")
          console.log(this.state.isAuthenticated)
        } else {
          console.log('Get user: no user');
          this.setState({
            isAuthenticated: false,
            loggedIn: false,
            username: null
          })
          console.log("this.state.isAuthenticated value:")
          console.log(this.state.isAuthenticated)
        }
      })
      .catch((err) => {
        console.log('Error fetching authorized user.');
        console.log(err)
      });
  }

  render() {
    return (
      <div>
        <Router>
          <div>
            <Switch>
              <Route exact path="/" component={Home} />
              <Route exact path="/signin" component={Signin} />
              <Route exact path="/signup" component={Signup} />
              <PrivateRoute
                authed={this.state.isAuthenticated}
                path="/dashboard"
                component={Dashboard} />
              <Route component={NoMatch} />
            </Switch>
          </div>
        </Router>
      </div>
    )
  }

}

function PrivateRoute({ component: Component, authed, ...rest }) {
  console.log("PrivateRoute")
  console.log("authed value:")
  console.log(authed)
  return (
    <Route
      {...rest}
      render={(props) => (authed === true)
        ? (<Component {...props} />)
        : (<Redirect
          to={{
            pathname: '/signin',
            state: { from: props.location }
          }}
        />)}
    />
  )
}

export default App;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...