【问题标题】:React not loading state properly on mount during axios call在 axios 调用期间,在挂载时反应未正确加载状态
【发布时间】:2020-09-17 00:38:29
【问题描述】:

基本上我正在制作一个基本的反应应用程序,它从数据库中获取一些数据,但我被困在基本设置上。

我的目的是让我的状态包含来自我的服务器查询我的数据库的响应。

我的响应是 100% 正常工作并按预期从 axios 调用发回数据,但是状态永远不会更新。

编辑:我正在尝试将电影沿链传递给名为 MovieList 的组件,我也提供了该组件的代码。

App.jsx

import React from 'react';
import axios from 'axios';

import MovieList from './MovieList.jsx';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {allMovies: []};
   
  }

  componentDidMount() {
    var that = this;
    axios.get('http://localhost:3000/api/movies')
      .then( res => {
        that.setState({allMovies: res.data});
      })
      .catch( err => {
        console.log(`Err @ [ App.jsx - componentDidMount ] ::: ${err}`);
      });
  }

  render() {
    return (
      <div>
        <h1>Hello World!</h1>
        <MovieList movies={this.state.allMovies} />
      </div>
    )
  }
}

MovieList.jsx

     import React from 'react';

class MovieList extends React.Component {
    constructor(props) {
        super(props);
        this.state = {};
        console.log(this.props); //EMPTY OBJECT MOVIES DIDN'T GET INTO PROPS
    }

    render() {
        return (
            <div>
                <h1>Test</h1>
            </div>
        )
    }
}

export default MovieList;

注意:我还在 mount 上记录了道具并尝试渲染它们,但它们是空的。

基本上,如果我尝试传递 this.state.allMovies 或 console.log 它,它总是只是初始的空数组。

也许我不明白如何异步设置状态?我在上一个学校项目中采用了类似的方法,并且似乎效果很好。

【问题讨论】:

  • 我猜在你的电影组件中应该是this.props.movies

标签: javascript reactjs axios


【解决方案1】:

您无需等待 axios 承诺解决,因此您只需记录组件挂载时的状态。使用以下方法之一记录更新的反应状态。

使用componentDidUpdate 记录更新的状态。

componentDidMount() {
  console.log(this.state);
}

使用setState回调函数记录状态

componentDidMount() {
  var that = this;
  axios.get('http://localhost:3000/api/movies')
    .then( res => {
      console.log(res.data);
      that.setState(
        { allMovies: [res.data] },
        () => console.log(this.state), // <-- setState callback function
      );
    })
    .catch( err => {
      console.log(`Err @ [ App.jsx - componentDidMount ] ::: ${err}`);
    });
}

【讨论】:

  • @chrisalopez1337 那么问题出在MovieList 上?它不是“看到”作为道具传递给它的更新状态吗?您可以尝试创建一个 running 代码框来重现问题并在此处分享吗?
  • @chrisalopez1337 类似的情况,构造函数只运行一次,所以在初始渲染时它接收传递给它的空数组。此外,在构造函数中,this.props 还没有真正定义,如果你想记录收到的道具,那么使用传递给构造函数的props 参数,即console.log(props)。在子组件中使用像 componentDidUpdate 这样的生命周期函数来记录道具,因为它们更新和重新渲染组件。
  • @chrisalopez1337 构造函数应该是一个副作用为零的纯函数...使用componentDidMount 来发出任何副作用,例如在安装组件时进行日志记录。
  • @chrisalopez1337 它抛出是因为在初始渲染时this.props.movies[0] 未定义。您可以使用可选链接this.props.movies[0]?.title 来防范空值/未定义值。 movies 是一个数组,所以通常你会映射结果,即this.props.movies.map(movie =&gt; (&lt;div&gt;{movie.title}&lt;/div&gt;)),如果你想显示“加载”状态,那么你可以有条件地渲染它,比如this.props.movies.length ? this.props.movies.map(movie =&gt; (&lt;div&gt;{movie.title}&lt;/div&gt;)) : '...Loading Movies'
  • @chrisalopez1337 不用担心。如果问题得到解决并且解释有帮助,请接受答案并投票。干杯。
【解决方案2】:

你永远不会在你的构造函数中看到它,因为当你的组件被实例化时,它是用一个空数组来完成的。

如果您在componentDidUpdaterender 中执行console.log(this.props),您将看到它。

这是因为当App 被挂载时,你的组件将一个名为[] 的电影道具传递给MovieList。在电影从服务器返回后(并且您更新了App 的状态),App 将再次渲染并传递从服务器返回的数组,从而导致您的 MovieList 组件再次渲染。它的constructor 不会被调用,因为它已经被实例化了,但是MovieList 会再次调用componentDidUpdaterender

class MovieList extends React.Component {
    constructor(props) {
        super(props);
        this.state = {};
    }

    render() {
        console.log(this.props); // you'll see this get logged twice - once with an empty array for movies and once with the movies returned from the server.
      
        return (
            <div>
                <h1>Test</h1>
            </div>
        )
    }
}

【讨论】:

    猜你喜欢
    • 2012-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-30
    • 1970-01-01
    • 2021-11-14
    • 1970-01-01
    • 2020-12-14
    相关资源
    最近更新 更多