【问题标题】:React Updating parent state with API call and then update child使用 API 调用响应更新父状态,然后更新子状态
【发布时间】:2020-06-13 10:45:53
【问题描述】:

我希望我的孩子在我的父母更新其状态时重新渲染。看起来很简单,但我还没有让它工作。

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

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

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

我的 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;

【问题讨论】:

  • 使用componentDidMount 而不是componentWillMount
  • 另外,您的 PrivateRoute 中不需要“this.state.auth”,因为您可以使用道具 (this.props.auth)
  • @RedBaron componentDidMount 不起作用,因为在第一次渲染时它会重定向。

标签: javascript reactjs state


【解决方案1】:

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();
  }

在子组件中,你必须从 props 中设置状态。

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

【讨论】:

  • 我更改了这样的代码,但它似乎仍然在更改“loggedInStatus”之前呈现重定向。
  • @S.Martinsson 在子组件中,您没有从构造函数中的道具设置状态。您在 componentDidUpdate 中设置状态,该状态将在第一次渲染调用后执行,在渲染函数中,您的身份验证状态将始终为 false。我已经更新了我的代码,您必须更改子组件中的构造函数才能从道具设置身份验证。
  • 同样的问题,由于某种原因,构造函数运行时 props.auth 似乎为假。
  • 我通过添加一个“加载”状态解决了这个问题,该状态在 API 调用完成之前呈现一个空白页面!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-02
  • 2021-03-31
  • 2020-01-23
  • 2018-02-09
  • 1970-01-01
  • 2018-07-08
  • 2017-04-06
相关资源
最近更新 更多