猿问

在获取并等待之后,React中的“无法读取未定义的属性”

我是React的新手,并且在获取时遇到问题:


我一直在做一个反应项目,根据用户选择的公司,我必须从五个不同的URL中获取。我已经多次更改了代码,但无法正常工作。


我尝试了componentDidMount(但它只被调用过一次,并且我想获取许多网址),并使用“ 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%的时间)数据没有到达,而我试图访问它。


白猪掌柜的
浏览 262回答 3
3回答

料青山看我应如是

我找到了一个解决方案:只需在返回之前在渲染中放置if语句,说“符号是否已更改?如果是,则获取,否则不”

MMTTMM

此问题的原因setState()是异步的。在您的情况下,这意味着状态已在此处进行更改:this.setState({data: data, loading: false });在随后的调用this.setValues();(它本身依赖于data组件状态中定义的对象)上不是立即可观察到的。这些情况的解决方案是在setState()方法上使用第二个回调参数来运行依赖于相应状态更改的逻辑:/* The state change will be observable when setValues() is called viathe callback */this.setState({data: data, loading: false }, () => {&nbsp; &nbsp; this.setValues();&nbsp; &nbsp;&nbsp;});至于你的组件实现的建议,考虑修改render()方法,这样day,open和higher被访问和渲染render()直接,因为你似乎是做,而不是在其他地方缓存这些值。所以尝试这样的事情:render() {&nbsp; &nbsp; this.fetch_data();&nbsp; &nbsp; if(this.state.loading || !this.state || !this.state.data) {&nbsp; &nbsp; &nbsp; return <div>Loading :D...</div>&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; /* Call to setValues() no longer needed */&nbsp; &nbsp; &nbsp; const day = this.state.data["Meta Data"]["3. Last Refreshed"];&nbsp; &nbsp; &nbsp; const open = this.state.data["Time Series (Daily)"][day]["1. open"];&nbsp; &nbsp; &nbsp; const higher = this.state.data["Time Series (Daily)"][day]["2. high"];&nbsp; &nbsp; &nbsp; return (&nbsp; &nbsp; &nbsp; &nbsp; <div>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <h2>Symbol: {symbol}</h2>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <p>Url: {url}</p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <ul>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <li>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Open price: {open}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </li>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <li>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Higher price: {higher}&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </li>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </ul>&nbsp; &nbsp; &nbsp; &nbsp; </div>&nbsp; &nbsp; &nbsp; );&nbsp; &nbsp; }&nbsp; }
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答