用API调用React更新父状态,然后更新子状态

时间:2020-06-13 10:45:53

标签: javascript reactjs state

我希望我的孩子在父母更新其状态时重新提交。看起来很简单,但我还没有开始工作。

在App.js中,我在componentWillMount中进行API调用。然后,我希望“ PrivateRoute”更新状态“ auth”,但似乎componentDidUpdate从未运行,而且我总是被重新分配。

代码的目的是API调用检查用户是否具有有效的身份验证令牌,然后将“ isLoggedIn”状态设置为true或false。这应该使子级“ PrivateRoute”要么重定向(如果isLoggedIn为false),要么呈现另一个页面(如果isLoggedIn为true)。

我已经检查了很多其他类似的问题,但到目前为止,没有解决方案。

我的app.js:

import React, { Component } from "react";

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

import axios from "axios";

import PrivateRoute from "./components/PrivateRoute";

// Pages
import IndexPage from "./pages/index";
import HomePage from "./pages/home";

class App extends Component {
  constructor() {
    super();
    console.log("Constructor");
    this.state = {
      loggedInStatus: false,
      test: "TEST",
    };
  }

  // Checks if user is logged in
  checkAuth() {
    let token = localStorage.getItem("token");
    let isLoggedIn = false;
    if (token === null) token = "bad";

    console.log("Making API call");
    // API call
    axios
      .get("http://localhost:8000/authentication/checkAuth", {
        headers: { Authorization: "token " + token },
      })
      .then((res) => {
        console.log("Updateing state");
        this.setState({ loggedInStatus: true });
      })
      .catch((error) => {
        console.log("Updating state");
        this.setState({ loggedInStatus: false });
      });
    return isLoggedIn;
  }

  componentWillMount() {
    this.checkAuth();
  }

  render() {
    //console.log("Render");
    // console.log("isLoggedIn: ", this.state.loggedInStatus);

    return (
      <Router>
        <Switch>
          <PrivateRoute
            exact
            path="/home"
            component={HomePage}
            auth={this.state.loggedInStatus}
          />
          <Route exact path="/" component={IndexPage} />
        </Switch>
      </Router>
    );
  }
}

export default App;

PrivateRoute.jsx:

import { Redirect } from "react-router-dom";
import React, { Component } from "react";

class PrivateRoute extends Component {
  state = {};

  constructor(props) {
    super(props);
    this.state.auth = false;
  }

  // Update child if parent state is updated
  componentDidUpdate(prevProps) {
    console.log("Component did update");
    if (this.props.auth !== prevProps.auth) {
      console.log("Child component update");
      this.setState({ auth: this.props.auth ? true : false });
    }
  }

  render() {
    console.log("Props: ", this.props);
    console.log("State: ", this.state);
    //alert("this.props.auth: ", this.props.auth);
    //alert("TEST: ", this.props.test);
    if (this.props.auth) {
      return <h1>Success!</h1>;
      //return <Component {...this.props} />;
    } else {
      return (
        <Redirect
          to={{ pathname: "/", state: { from: this.props.location } }}
        />
      );
    }
  }
}

export default PrivateRoute;

1 个答案:

答案 0 :(得分:0)

如果要在组件中首次呈现之前获得身份验证状态,则应该同步checkAuth。

您的checkAuth将立即返回,从而使身份验证状态始终为false。

async checkAuth() {
    try {
        let token = localStorage.getItem("token");
        let isLoggedIn = false;
        if (token === null) token = "bad";
        const res = await axios
            .get("http://localhost:8000/authentication/checkAuth", {
                headers: {Authorization: "token " + token},
            })
        console.log("Updateing state");
        this.setState({loggedInStatus: true});
    } catch (e) {
        // for non 2XX axios will throw error
        console.log("Updating state");
        this.setState({loggedInStatus: false});
    }
}

async componentWillMount() {
    await this.checkAuth();
  }

在子组件中,您必须通过道具设置状态。

constructor(props) {
    super(props);
    this.state.auth = props.auth;
  }