【问题标题】:Not able to fetch data from server in my ReactJs site无法从我的 ReactJs 站点中的服务器获取数据
【发布时间】:2021-07-15 17:20:59
【问题描述】:

从 JSON 获取数据时出现未定义的数据类型错误

我搜索了很多地方,但没有得到合适的答案

import SavedData from "./SavedData";

export default class Saved extends React.Component {
  constructor() {
    super();
    this.state = {
      loading: true,
      datas: [],
    };
  }

  async componentDidMount() {
    const url = "https://todo-list-site.herokuapp.com/todo-data";
    const response = await fetch(url);
    const todoData = response.json().then((res) => {
      this.setState({ datas: res });
    });
  }

  render() {
    console.log(this.state.datas[0].description);   //not able to get data
    return (
      <div>
        {/* {this.state.datas.map((items) => (
          <SavedData
            key={items.countTodo}
            title={items.title}
            desc={items.desc}
          />
        ))} */}
      </div>
    );
  }
}

请有人帮助我,以便我可以继续

【问题讨论】:

  • 您的渲染在请求完成之前运行,而您似乎没有处理它。

标签: json reactjs http backend


【解决方案1】:

就像 Dave Newton 在 cmets 中指出的那样,渲染是在请求完成之前触发的。这是正常现象,您只需妥善处理即可。

如果您看到此codesandbox 的控制台日志,您可以看到最初this.state.datas 只是一个空数组[] - 因此任何访问this.state.datas[0].description 的尝试都将是undefined。只有在请求完成时更新状态后,日志才会显示检索到的数据 - 这是因为根据 React Componentmount lifecyclerender()componentDidMount() 之前调用,并且请求也在异步。

这很常见,甚至官方 React docs 推荐在 componentDidMount() 中进行 HTTP 调用。文档还提供了example 来处理此问题。

import SavedData from "./SavedData";

export default class Saved extends React.Component {
  constructor() {
    super();
    this.state = {
      loading: true,  // we initially set this to true
      datas: [],
    };
  }

  async componentDidMount() {
    const url = "https://todo-list-site.herokuapp.com/todo-data";
    const response = await fetch(url);
    const todoData = response.json().then((res) => {
      this.setState({
        datas: res,
        loading: false  // when the request is complete, we set this to false
      });
    });
  }

  render() {
    if (this.state.loading) {
      // during the first render, loading will be true and we
      // can return a loading message or a spinner
      return (
        <div>Loading...</div>
      );
    }

    // when render is called after the state update, loading will be false
    // and this.state.datas will have the fetched data
    console.log(this.state.datas[0].description);
    return (
      <div>
        {this.state.datas.map((items) => (
          <SavedData
            key={items.countTodo}
            title={items.title}
            desc={items.desc}
          />
        ))}
      </div>
    );
  }
}

【讨论】:

  • 在我写这个答案时,URL https://todo-list-site.herokuapp.com/todo-data 正在返回一些 JSON 数据。但现在,它似乎返回了一个空数组[]。因此,codeandbox 也会在第二个 render() 期间显示 [](从技术上讲,它只是显示获取的数据)。
【解决方案2】:

您的数据状态最初是一个空数组,直到您的 componentDidMount 触发并设置状态。因此,在设置状态之前,您的控制台日志将是未定义的。为了解决这个问题,您必须等待 this.state.datas[0] 为真,然后才能访问数组中的第一个对象描述。以下代码似乎按预期工作

import React from "react";

export default class Saved extends React.Component {
  constructor() {
    super();
    this.state = {
      loading: true,
      datas: []
    };
  }

  async componentDidMount() {
    const url = "https://todo-list-site.herokuapp.com/todo-data";
    const response = await fetch(url);
    response.json().then((res) => {
      this.setState({ datas: res });
    });
  }

  render() {
    console.log(this.state.datas[0] && this.state.datas[0].description);
    return (
      <div>
        {this.state.datas.map((items, i) => (
          <div key={i}>
            <div> title={items.title}</div>
            <div> desc={items.description}</div>
          </div>
        ))}
      </div>
    );
  }
}

【讨论】:

    猜你喜欢
    • 2017-12-26
    • 1970-01-01
    • 1970-01-01
    • 2013-07-27
    • 2020-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多