javascript - 为什么我得到的是 "return _this.state.data"而不是 JSON 对象

标签 javascript json ajax reactjs

我有一个父组件执行 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;

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

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

最佳答案

首先,,您应该更改 data您发送至 InfoList 的 Prop 成为this.state.data而不是匿名函数。所以:<InfoList data={this.state.data} />

但是,主要问题在于使用 componentDidMount在子组件中,当真的你应该使用componentWillReceiveProps相反。


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

componentDidMount生命周期 Hook 在初始 render 之前被调用一次.

在您的子组件中,位于 componentDidMount您正在尝试记录 this.state.data - 但此状态基于构造函数中设置的内容,即作为 data 传入的内容首次安装时的 Prop InfoList .那是 [] ,因为 InfoBox尚未收到来自其 Ajax 调用的返回数据。换句话说:

InfoList.componentDidMount() fired before InfoBox.loadDonationsFromServer() got back its response. And InfoList.componentDidMount() does not get fired again.

componentWillReceiveProps 在 props 改变时被调用

相反,您的子组件应该使用 componentWillReceiveProps生命周期钩子(Hook)。每次组件接收到新 Prop 时都会调用它。一旦 parent 的状态发生变化(负载捐赠返回后),它就会将新的 Prop 传递给 child 。在 componentWillReceiveProps , child 可以拿走这些新 Prop 并更新他的状态。


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


其他资源

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

  • 关于 React 生命周期钩子(Hook)的优秀快速引用是 React Cheat Sheet )

关于javascript - 为什么我得到的是 "return _this.state.data"而不是 JSON 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54896750/

相关文章:

javascript - 如何使用 Meteor 中的 Iron Router 将自定义 ID 分配给动态生成的 URL?

mysql - 如何使用 common_schema 从 JSON 中提取值?

mysql - 如何将 JSON 对象转换为 MySQL 行?

javascript - 无法访问 Web 服务 - JQuery Ajax 请求

javascript - 对于 HTTP OPTIONS 请求,拥有响应正文有什么意义吗?

Javascript:实现 100% 防篡改私有(private)变量的方法?

javascript - jQuery 菜单 - 如何在菜单上放置箭头来表示子菜单?

javascript - Youtube 视频事件未触发 [在本地或其他地方进行测试时]?

javascript - Vanilla JS |也包含属性的可调用对象

javascript - Angular 替代 $http