Javascript 如何在 REACT 中每分钟为仪表板调用一个 API

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/48601813/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 04:11:11  来源:igfitidea点击:

How to call an API every minute for a Dashboard in REACT

javascriptreactjs

提问by Nacho Lee

I've made a dashboard in React. It has no active updating, no buttons, fields or drop-downs. It will be deployed on a wall TV for viewing. All panels (9 total) are updated through the API call. The initial call (seen below) works, and all JSON data is fetched and the dashboard is initially updated.

我在 React 中制作了一个仪表板。它没有主动更新,没有按钮、字段或下拉菜单。它将部署在墙上电视上以供观看。所有面板(共 9 个)都通过 API 调用进行更新。初始调用(如下所示)有效,所有 JSON 数据都被提取,仪表板初始更新。

BOTTOM LINE PROBLEM: I need to call the API every 30 sec to 1 minute after the initial call to check for updates.

底线问题:我需要在初始调用后每 30 秒到 1 分钟调用一次 API 以检查更新。

I have attempted "setInterval" inside the componentDidMount() as suggested by people on here answering others' questions and I get an error "await is a reserved word". I've read about forceUpdate() which seems logical for my use case given what the facebook/react page says about it. But, I've read on here as well to stay away from that...

我已经尝试在 componentDidMount() 中使用“setInterval”,正如这里回答其他人问题的人所建议的那样,我收到一个错误“await 是一个保留字”。我已经阅读了有关 forceUpdate() 的内容,考虑到 facebook/react 页面对此的描述,这对我的用例来说似乎是合乎逻辑的。但是,我也在这里阅读以远离那个......

The code below is a light version of the code I'm using. I've removed many of the components and imports for brevity's sake. Any help would be greatly appreciated.

下面的代码是我正在使用的代码的精简版。为简洁起见,我删除了许多组件和导入。任何帮助将不胜感激。

import React, { Component } from 'react';

import Panelone from './Components/Panelone';
import Paneltwo from './Components/Paneltwo';

class App extends Component {

  state = {
      panelone: [],
      paneltwo: []
    }

 async componentDidMount() {
      try {
        const res = await fetch('https://api.apijson.com/...');
        const blocks = await res.json();
        const dataPanelone = blocks.panelone;
        const dataPaneltwo = blocks.paneltwo;

        this.setState({
          panelone: dataPanelone,
          paneltwo: dataPaneltwo,
        })
      } catch(e) {
        console.log(e);
      }

  render () {
    return (
      <div className="App">
        <div className="wrapper">
          <Panelone panelone={this.state} />
          <Paneltwo paneltwo={this.state} />
        </div>
      </div>
    );
  }
}

export default App;

采纳答案by Aaditya Thakkar

In order to use await, the function directly enclosing it needs to be async. According to you if you want to use setIntervalinside componentDidMount, adding async to the inner function will solve the issue. Here is the code,

为了使用await,直接封闭它的函数需要是async。根据您的说法,如果您想使用setIntervalinside componentDidMount,将 async 添加到内部函数将解决问题。这是代码,

 async componentDidMount() {
          try {
            setInterval(async () => {
              const res = await fetch('https://api.apijson.com/...');
              const blocks = await res.json();
              const dataPanelone = blocks.panelone;
              const dataPaneltwo = blocks.paneltwo;

              this.setState({
                panelone: dataPanelone,
                paneltwo: dataPaneltwo,
              })
            }, 30000);
          } catch(e) {
            console.log(e);
          }
    }

Also instead of using setInterval globally, you should consider using react-timer-mixin. https://facebook.github.io/react-native/docs/timers.html#timermixin

此外,您应该考虑使用 react-timer-mixin,而不是全局使用 setInterval。https://facebook.github.io/react-native/docs/timers.html#timermixin

回答by Sajith Dilshan

Move the data fetch logic into a seperate function and invoke that function using setIntervalin componentDidMountmethod as shown below.

将数据获取逻辑移动到一个单独的函数中,并使用setIntervalincomponentDidMount方法调用该函数,如下所示。

  componentDidMount() {
    this.loadData()
    setInterval(this.loadData, 30000);
  }

  async loadData() {
     try {
        const res = await fetch('https://api.apijson.com/...');
        const blocks = await res.json();
        const dataPanelone = blocks.panelone;
        const dataPaneltwo = blocks.paneltwo;

        this.setState({
           panelone: dataPanelone,
           paneltwo: dataPaneltwo,
        })
    } catch (e) {
        console.log(e);
    }
  }

Below is a working example

下面是一个工作示例

https://codesandbox.io/s/qvzj6005w

https://codesandbox.io/s/qvzj6005w

回答by Union In Design

I figured I'd chime in with a slightly revised approach that uses recursion via a setTimeout call within the function block. Works the same...maybe slightly cleaner to have the function call itself from within, instead of doing this elsewhere in your code?

我想我会加入一种稍微修改的方法,该方法通过功能块内的 setTimeout 调用使用递归。工作原理相同......也许从内部调用函数本身会更简洁,而不是在代码的其他地方执行此操作?

This articleexplains the reasoning in a bit more depth...but I've been using this approach for several dashboards at work - does the job!

这篇文章更深入地解释了推理……但我一直在将这种方法用于工作中的几个仪表板 - 完成工作!

Would look something like this:

看起来像这样:

class MyComponent extends React.Component
//create the instance for your interval
intervalID;
constructor(props) {
    super(props);
    this.state = {
        data: [],
        loading: false,
        loadingMap: false,

        //call in didMount...
        componentDidMount() {
          this.getTheData()
        }

 getTheData() {
 //set a loading state - good practice so you add a loading spinner or something
   this.setState({loading: true}), () => {
 //call an anonymous function and do your data fetching, then your setState for the data, and set loading back to false
   this.setState({
       data: fetchedData,
       loading: false
       )}     }
 //Then call the function again with setTimeout, it will keep running at the specified //interval...5 minutes in this case
            this.intervalID = setTimeout(
              this.getTheData.bind(this),
              300000
            );

          }
        }
        //Important! Be sure to clear the interval when the component unmounts! Your app might crash without this, or create memory leaks!
        componentWillUnmount() {
          clearTimeout(this.intervalID);
        }

Sorry if the formatting got a little off. Haven't tried this with Hooks yet but I think you'd have a similar implementation in a useEffect call? Has anyone done that yet?

对不起,如果格式有点偏离。还没有用 Hooks 尝试过这个,但我认为你在 useEffect 调用中会有类似的实现?有没有人这样做过?