【问题标题】:Why am I getting "return _this.state.data" instead of JSON object为什么我得到“return _this.state.data”而不是 JSON 对象
【发布时间】:2019-07-20 15:50:33
【问题描述】:

我有一个父组件执行 AJAX 调用以获取 JSON 对象。我做了一些 console.log 来确保父组件中的数据是正确的,但是当我通过 props 时,我得到一个值:

ƒ data() {
  return _this.state.data;
}

到目前为止,我所做的似乎很简单,所以我找不到问题所在。

父组件:

class InfoBox extends Component {
  state = {
    data: []
  };

  componentDidMount = () => {
    this.loadDonationsFromServer();
    setInterval(this.loadDonationsFromServer, this.props.pollInterval);
  };

  loadDonationsFromServer = () => {
    $.ajax({
      url: "https://jsonplaceholder.typicode.com/comments",
      dataType: "json",
      cache: false,
      success: data => {
        this.setState({ data });
      },
      error: (xhr, status, err) => {
        console.error(status, err.toString());
      }
    });
  };

  render = () => {
    return (
      <React.Fragment>
        <h1>Information</h1>
        <InfoList
          data={() => this.state.data}
        />
      </React.Fragment>
    );
  };
}

export default DonationBox;

子组件:

class InfoList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      data: this.props.data
    };
  }

  componentDidMount() {
    console.log(this.state.data);
    //logs: ƒ data() {
    //         return _this.state.data;
    //      }
  }
  render() {    
    return <div> Placeholder </div>;
  }
}

export default InfoList;

我尝试在子组件中使用绑定,但仍然得到同样的结果:

  constructor(props) {
    super(props);
    this.state = {
      data: this.props.data
    };
    this.checkData = this.checkData.bind(this);
  }

  componentDidMount() {
    this.checkData();
  }

  checkData = () => {
    console.log(this.state.data);
  };

【问题讨论】:

  • 在您的父组件中,您声明了一个类 InfoBox,但导出了一个类 DonationBox - 这只是一个错字,对吧?

标签: javascript json ajax reactjs


【解决方案1】:

那是因为传入的 data 属性是一个函数。

改变

<InfoList data={() => this.state.data} />

<InfoList data={this.state.data} />

只是一点点,您实际上并不需要子组件中的构造函数来定义状态。只需按照您在父组件中的方式定义它即可。

【讨论】:

  • 去掉匿名函数后,只是返回一个空数组。以与父级相同的方式定义状态也不能解决它。您还发现其他可能有问题的地方吗?
  • 看起来您的主要问题是空数组,而不是 return _this.state.data 函数值,因为您已更改代码以删除匿名函数。您可能需要更新您的帖子(标题和代码)以更准确地反映您现在面临的实际问题(使用空数组)。
【解决方案2】:

首先,是的,您应该将发送给InfoListdata 属性更改为this.state.data,而不是匿名函数。所以:&lt;InfoList data={this.state.data} /&gt;

但是,主要问题是在子组件中使用componentDidMount,而实际上您应该使用componentWillReceiveProps


componentDidMount 只调用一次,它不会等待你的 AJAX

componentDidMount 生命周期挂钩在初始 render 之前被调用一次。

在您的子组件中,在componentDidMount,您正在尝试记录this.state.data - 但此状态基于构造函数中设置的内容,这是您第一次安装@ 时作为data 属性传入的内容987654335@。那是[],因为InfoBox 还没有从它的Ajax 调用中接收回数据。换句话说:

InfoList.componentDidMount()InfoBox.loadDonationsFromServer() 得到回复之前被解雇。 InfoList.componentDidMount()不会再次被解雇。

componentWillReceiveProps 在 props 改变时被调用

相反,您的子组件应该使用componentWillReceiveProps 生命周期挂钩。每次组件接收到新的 props 时都会调用它。一旦父母的状态发生变化(在负载捐赠返回后),它就会将新的道具传递给孩子。在componentWillReceiveProps 中,孩子可以获取这些新的道具并更新他的状态。


我创建了一个code sandbox,它通过一堆日志语句向您展示什么时候会发生什么,以及您的道具和状态在生命周期的各个点上的样子。我没有实际执行 ajax 提取,而是等待 2 秒来模拟提取。在InfoList.js中,componentWillReceiveProps的代码目前被注释掉了;通过这种方式,您可以了解事物的现状。删除 cmets 并开始使用 componentWillReceiveProps 后,您将看到它们是如何得到修复的。


其他资源

  • 这是helpful article,它几乎描述了您所面临的完全相同的问题。

  • React Cheat Sheet) 是 React 生命周期钩子的一个极好的快速参考)

【讨论】:

  • 就是这样!您在 componentWillReceiveProps 函数中的条件语句解决了这个问题。谢谢,阿尔文。