简体   繁体   English

使用REACT.JS从JSON文件中的提取请求中获取未定义的值

[英]Undefined getting value from fetch request in a JSON file using REACT.JS

I'm coming from a Vue environment I'm a bit confused with this, I read some other question similar to this but I couldn't make it work, 我来自Vue环境,对此我感到有些困惑,我读到了其他与此类似的问题,但我无法使其正常运行,

why I can't echo out the value of a nested object getting from a fetch request? 为什么我无法回显从获取请求中获取的嵌套对象的值?

I console.log after setState and I got the values but in the render is undefined, 我在setState之后输入console.log并得到了值,但是在render中是未定义的,

import React, { Component } from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class App extends Component {
  constructor() {
    super();
    this.state = {
      isLoading: true,
      articles: {}
    };
  }

  componentDidMount() {
    this.setState({ loading: true });
    fetch("./articles.json")
      .then(response => response.json())
      .then(result => {
        this.setState({
          isLoading: false,
          article: result.blog.article
        });
        console.log(
          "componentDidMount__this.state.article=",
          this.state.article.link.title
        ); //this gets the value
      })
      .catch(error => {
        console.error(error);
      });
  }

  render() {
    //let articleTitle;
    // this gets error ----> console.log(this.state.article.link.title);
    // because .link is undefined

    // console.log(this.state.article);
    // if (this.state.article !== "undefined") {
    //   console.log("wait what?..");
    // if I changed the state in fetch why this stil
    //   articleTitle = this.state.article.link.title;
    // } else {
    //   articleTitle = "";
    // }

    // I assign "this.state.article.link.title" to a variable so I can avoid the error,
    //
    return (
      <div className="App">
        {/*<h1>{articleTitle}</h1> */}
        <h1>{this.state.article.link.title}</h1>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

articles.json article.json

{
  "blog": {
    "article": {
      "id": 1,
      "title": " 1 lorem ipsum",
      "description": "lorem ipsum",
      "image": {
        "desktop": "https://via.placeholder.com/900x500?text=desktop",
        "tablet": "https://via.placeholder.com/600x400?text=tablet",
        "mobile": "https://via.placeholder.com/320x320?text=mobile"
      },
      "link": {
        "title": "lorem link",
        "url": "#"
      },
      "author": {
        "avatar": "https://via.placeholder.com/125x125?text=125x125",
        "name": "lorem ipsum"
      }
    }
  }
}

https://codesandbox.io/s/wo65w21kl5 https://codesandbox.io/s/wo65w21kl5

You have to put check before using dynamic states in render as it is called on both component mount and update. 您必须在渲染中使用动态状态之前进行检查,因为在组件安装和更新上都调用了动态状态。

This should work fine: 这应该工作正常:

{this.state.isLoading ? '' : this.state.article.link.title}

It appears that this.state.article.link.title is being referenced when this.state.article === undefined . 看来, this.state.article.link.title当被引用this.state.article === undefined

The solution is to retrieve this.state.article.link.title in a safer manner. 解决方案是以更安全的方式检索this.state.article.link.title

This is typically achieved by leveraging short-circuit evaluation . 这通常通过利用短路评估来实现。 I've also used destructuring assignment and default parameters in the example below. 在下面的示例中,我还使用了销毁分配默认参数

Assigning default values to this.state is also recommended, especially when dealing with indeterminate data. 还建议为this.state分配默认值,尤其是在处理不确定数据时。

// Default `this.state`.
this.state = {
  article: {link: {title: ''}},
  articles: {},
  isLoading: true,
}

// Safe retrieval of `title`.
const {article = {}} = this.state
const {link = {}} = article.link
const title = link.title || ''

TRY this 尝试这个

   import React, { Component } from "react";
    import ReactDOM from "react-dom";

    import "./styles.css";

    class App extends Component {
      constructor() {
        super();
      }
      state = {
        isLoading: true,
        articles: {}
      };
      componentDidMount() {
        this.setState({ loading: true });
        fetch("./articles.json")
          .then(response => response.json())
          .then(result => {
            this.setState({
              isLoading: false,
              articles: result.blog.article
            });
          })
          .catch(error => {
            console.error(error);
          });
      }

      render() {
        let Test = this.state.articles ? (
          <div className="App">
            <h1>{this.state.articles.title}</h1>
          </div>
        ) : null;

        console.log(this.state.articles.title);
        return <div>{Test}</div>;
      }
    }

    const rootElement = document.getElementById("root");
    ReactDOM.render(<App />, rootElement);

It seems that render method is invoked three times before fetch method finish, so in render method this.state.articles is empty object. 似乎render方法在fetch方法完成之前被调用了3次,因此在render方法中this.state.articles是空对象。 You also wonders why guy from the tutorial does not have this issue, well in tutorial you mentioned object: this.state.character.name was used and in your code this.state.articles.link.title . 您还想知道为什么本教程中的家伙没有这个问题,在本教程中您提到了 object:使用了this.state.character.name ,在您的代码中使用了this.state.articles.link.title This is the difference, because it is acceptable to use this.state.character.name (it refers to property from empty object so it will return undefined, whereas your this.state.article.link.title (it tries to access to property on object that does not exist). You can check it in console: 这是不同的,因为可以使用this.state.character.name (它引用空对象中的属性,因此它将返回未定义的值,而您的this.state.article.link.title (它尝试访问属性)在不存在的对象上)。您可以在控制台中检查它:

const obj = {};
console.log(obj.property); //undefined
console.log(obj.link.title); // Uncaught TypeError: Cannot read property 'title' of undefined

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM