值未正确传递给函数

时间:2018-12-03 02:23:07

标签: reactjs react-router-dom

我现在还很陌生,所以这可能是一个简单的问题。如果标题不正确,请提前道歉。

我正在尝试使用react-router-dom做一条受保护的路由。我以为我的代码正确,但是由于某些原因,当用户登录并调用PrivateRoute时,身份验证信息可能没有正确传递,这可能是我的ID-10-T错误。下面是我的代码和单击/ 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

似乎在componentWillMount之前正在处理PrivateRoute,但是我不确定如何防止这种情况。

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

您可能需要在代码中解决一些问题。

  1. 您不必绑定componentWillMount或任何生命周期方法。
  2. componentWillMount更改为componentDidMount。在挂载componentWillMount组件之前调用作为App挂载的组件之后,最好进行api调用。
  3. PrivateRoute仅在调用App组件的render方法时才被调用。但是由于所有API调用都是异步的,因此App组件的render方法将在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;