【问题标题】:Using react, it is possible to make an app that uses axios, setInterval, setTimeout, and map?使用react,可以做一个使用axios、setInterval、setTimeout、map的app吗?
【发布时间】:2018-06-30 11:30:52
【问题描述】:

我开始怀疑我有一个问题没有解决方案,除非我放弃 React 并返回到 jQuery。我想创建一个类似于https://tenno.tools/https://deathsnacks.com/wf/ 的应用程序,这些站点会获取 JSON 数据并定期更新。

我想制作一个使用 axios 的 react 应用,通过 setTimeout 每分钟刷新一次数据,因为数据经常变化。

  axiosFunc = () => {

    axios.get('https://api.warframestat.us/pc').then(results => {
      this.setState({
        alerts: results.data.alerts
      });

      setTimeout(this.axiosFunc,1000 * 60);
    })
  }
  componentDidMount() {
    this.axiosFunc();
  }

接下来我需要使用 map 循环遍历警报数组的对象,并根据对象的活动数据制作各个组件。

render() {

    return (
      <main className="content">
        <header>{this.state.whichEvent.toUpperCase()}</header>

        {this.state.alerts.map(alert => {
          //Variables that pull time based data from the objects go here, and go into the component as props 
            <AlertsBox key={alert.id}/>
        })}
      </main>
    );
  }

然后我使用组件中的 props 和 state 来制作一个计时器,因为来自 JSON 文件的数据有过期日期...

let timer = () => {
      //Extract the data from the original string
      //Convert the UTC to locale time

      let seconds = Math.round((this.state.eta/1000) % 60);
      let minutes = Math.floor( (this.state.eta/1000/60) % 60 );
      let hours = Math.floor( (this.state.eta/(1000*60*60)) % 24 );
      let days = Math.floor( this.state.eta/(1000*60*60*24) );

      return `${days >= 1? days + " days" : ""} ${hours >= 1? hours + " hrs" : ""} ${minutes} min ${seconds} sec`
    }

所有这些都有效。我能够看到来自 JSON 的动态数据,因为它们进出,以及相应的时间。现在我只需要使用 setInterval 来让计时器每秒滴答一次。这可能吗?我在这里问了类似的问题

How can I return values once per second using react and axios?

但是,我又开始怀疑这实际上是不可能的。是吗?

【问题讨论】:

    标签: javascript reactjs axios


    【解决方案1】:

    您需要在axiosFunc 上使用setInterval,无需在网络请求中进行设置。这是一个每 5 秒调用一次 API 并呈现格式化日期的示例。

    class Example extends React.Component {
      constructor() {
        super();
        this.state = { alerts: [] };
      }
    
      axiosFunc = () => {
        axios.get('https://api.warframestat.us/pc').then(results => {
          this.setState({
            alerts: results.data.alerts,
          });
    
          console.log('Updated the data!', results);
        });
      };
    
      timer = time => {
        // Your timer code goes here, just printing out example data here.
        const date = new Date(time);
        return `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
      };
    
      componentDidMount() {
        this.axiosFunc();
        this.interval = setInterval(this.axiosFunc, 5000);
      }
    
      componentWillUnmount() {
        clearInterval(this.interval);
      }
    
      render() {
        if (!this.state.alerts.length) {
          return <div />;
        }
    
        // Sorting the alerts every time we render.
        const latest = this.state.alerts.sort((a, b) => {
          return new Date(b.activation) - new Date(a.activation);
        })[0];
    
        return <div>{this.timer(latest.activation)}</div>;
      }
    }
    
    ReactDOM.render(<Example />, document.getElementById('root'));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.17.1/axios.min.js"></script>
    
    <div id="root"></div>

    【讨论】:

    • 您好,考虑到源 JSON 数据会自行更改(因此会自动更新),我该如何跟上代码?在这里,您对索引进行了硬编码:return
      {this.timer(this.state.alerts[0].activation)}
      ,但如何保持动态?
    • 每次获取新数据时,都会再次调用render,您可以动态地对这些数据更改做出反应。我在示例中添加了一个排序机制,但您实际上可以在其中执行任何操作。
    • 只是想补充一点,如果您使用setTimeout,您可以将一个结束和下一个 API 调用的开始与超时分开。在您的示例中使用setInterval 时,您只需每x 个时间单位调用一次API,而不关心调用需要多长时间。有时在设置 5 秒的间隔时会出现一些问题,而您的通话时间会比这更长。
    【解决方案2】:

    这绝对是可能的。正如你所说,所有这些都有效——哪一部分实际上给你带来了麻烦?您是否在任何地方遇到错误?

    就个人而言,我会考虑在这样的应用程序中使用 Redux 和 React,因为我喜欢将数据的获取与数据的呈现分开,但这只是个人喜好。我有an example app that uses setInterval directly in a React component,以防从setTimeout 移动到setInterval 给你带来痛苦。

    【讨论】:

    • 问题是我不知道如何用 setInterval 更新定时器函数。它给了我一组数字,比如 7、8 和 9,而不是计时器。我尝试从组件内部更新状态,这会导致更多错误。
    • @Matiny 我猜你指的这组数字是setInterval 的返回值? setInterval 的返回值是间隔 ID - 当您准备停止侦听时(您可能希望在组件卸载时执行此操作,如示例中所示),您可以将该间隔 ID 提供给 clearInterval
    猜你喜欢
    • 1970-01-01
    • 2022-11-29
    • 2017-09-14
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    • 2015-08-23
    • 2021-12-08
    • 2018-04-21
    相关资源
    最近更新 更多