【问题标题】:"Cannot read property of undefined" in React after fetching and waiting获取和等待后React中的“无法读取未定义的属性”
【发布时间】:2019-08-28 23:50:48
【问题描述】:

我是 React 新手,但在获取时遇到问题:

我一直在做一个响应项目,我必须根据用户选择的公司从五个不同的 url 中获取。 代码我改过很多次了,还是不行。

我尝试使用 componentDidMount(但它只调用一次,并且我想获取许多 url),使用“while(!this.state)”忙于等待获取数据,然后再分配它等等。

获取函数:

async fetch_data() {
    var sel = this.props.select;
    symbol = companies[sel];
    url = 'https://www.alphavantage.co/query?function=' + func + '&symbol=' + symbol + '&outputsize=' + osize + '&apikey=' + api_key;
    var response = await fetch(url);
    var data = await response.json();

    while(!data);

    this.setState({data: data, loading: false });
    this.setValues();    
  }

设置值功能(修剪,使其不那么长):

setValues() {
    day = this.state.data["Meta Data"]["3. Last Refreshed"];
    open = this.state.data["Time Series (Daily)"][day]["1. open"];
    higher = this.state.data["Time Series (Daily)"][day]["2. high"];
  }

渲染函数(也被修剪):

render() {

    this.fetch_data();
    if(this.state.loading || !this.state || !this.state.data) {
      return <div>Loading :D...</div>
    } else {
      return (
        <div>
          <h2>Symbol: {symbol}</h2>
          <p>Url: {url}</p>
          <ul>
            <li>
              Open price: {open}
            </li>
            <li>
              Higher price: {higher}
            </li>
          </ul>
        </div>
      );
    }
  }

实际上,当用户选择公司时,我已经完成了该部分,并且符号(和 url)发生了变化...... 但问题是,当程序想要访问this.state.data["Time Series (Daily)"][day]["1. open"]; 时,它会崩溃,因为它正在获取和接收数据。

错误提示:

Unhandled Rejection (TypeError): Cannot read property '3. Last Refreshed' of undefined:

  42 | setValues() {
> 43 |   day = this.state.data["Meta Data"]["3. Last Refreshed"];
     | ^  44 |   open = this.state.data["Time Series (Daily)"][day]["1. open"];
  45 |   higher = this.state.data["Time Series (Daily)"][day]["2. high"];

应用程序并不总是崩溃,它会显示结果,但渲染组件会一直调用 this.fetch_data() 并且它会崩溃,因为有时(比如 80% 的时间)数据还没有到达,而我'我正在尝试访问它。

【问题讨论】:

  • 您可以删除while(!data);await 关键字将确保在调用 setState 之前为 data 分配一个值。
  • 试试这个替换 this.setValues() 到 requestAnimationFrame(this.setValues)
  • 它也不起作用:(

标签: javascript json reactjs fetch


【解决方案1】:

我找到了解决办法:

只需在渲染中的 return 之前放置一个 if 语句,说“符号是否已更改?如果是,则获取,否则不要”

【讨论】:

  • “符号是否已更改”是什么意思?您使用了什么方法/解决方案?我的项目中有同样的问题。
【解决方案2】:

我认为这是因为您正在调用 this.fetch_data();内部渲染() 这意味着首先你的状态中没有数据,在有数据之后你正在更新你的组件,所以你一次又一次地调用 this.fetch_data();

查看 React 组件生命周期:https://code.likeagirl.io/understanding-react-component-life-cycle-49bf4b8674de

另外一件事不需要写while(),因为你使用的是异步等待。

【讨论】:

  • 只有当 var "symbol" 改变它的值时,我该怎么做才能调用函数 fetch?感谢您的回答
【解决方案3】:

这个问题的原因是setState() is asynchronous.在您的情况下,这意味着这里的状态更改:

this.setState({data: data, loading: false });

在随后调用this.setValues(); 时不会立即观察到(这本身依赖于在组件状态中定义的data 对象)。 这些情况的解决方案是使用setState()方法上的第二个回调参数来运行依赖于相应状态变化的逻辑:

/* The state change will be observable when setValues() is called via
the callback */
this.setState({data: data, loading: false }, () => {

    this.setValues();    
});

作为您的组件实现的建议,考虑修改render() 方法,以便直接在render() 中访问和呈现dayopenhigher,而不是将这些值缓存在其他地方你似乎在做。所以尝试这样的事情:

render() {

    this.fetch_data();
    if(this.state.loading || !this.state || !this.state.data) {
      return <div>Loading :D...</div>
    } else {

      /* Call to setValues() no longer needed */

      const day = this.state.data["Meta Data"]["3. Last Refreshed"];
      const open = this.state.data["Time Series (Daily)"][day]["1. open"];
      const higher = this.state.data["Time Series (Daily)"][day]["2. high"];

      return (
        <div>
          <h2>Symbol: {symbol}</h2>
          <p>Url: {url}</p>
          <ul>
            <li>
              Open price: {open}
            </li>
            <li>
              Higher price: {higher}
            </li>
          </ul>
        </div>
      );
    }
  }

【讨论】:

  • 我已经修改了你所说的函​​数渲染,但它以同样的方式崩溃:(
  • 能否包含一份您的fetch() 请求返回的json 响应的副本?
猜你喜欢
  • 1970-01-01
  • 2022-01-18
  • 2021-10-15
  • 1970-01-01
  • 2021-09-10
  • 2020-02-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多