0

I'm trying to make a site that grabs data from a server with axios, then updates the final content once per second.

Here's the ajax request.

axiosFunc = () => {

    axios.get('https://api.warframestat.us/pc').then(results => {
      this.setState({
        alerts: results.data.alerts
      });
      setTimeout(this.axiosFunc,1000 * 60);
    })
  }
  componentDidMount() {
    this.axiosFunc();
  }

Then I return conditionally rendered components (AlertsBox) with data passed into it. They render based by time of day compared to time that they start and end.

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

    {this.state.alerts.map(alert => {
      let enddate = alert.expiry.substring(0,10);
      let endtime = alert.expiry.substring(11,19);

      let startdate = alert.activation.substring(0,10);
      let starttime = alert.activation.substring(11,19);

      let endAlert = new Date(`${enddate} ${endtime} UTC`).toLocaleString();

      let startAlert = new Date(`${startdate} ${starttime} UTC`).toLocaleString();

      let endNumber = Date.parse(endAlert);
      let startNumber = Date.parse(startAlert);

      return Date.now() > startNumber && Date.now() < endNumber ?
        <AlertsBox
          deadline={endAlert}
          activate={startAlert}
          timeOne={enddate}
          timeTwo={endtime}
          timeThree={startdate}
          timeFour={starttime}
          image={alert.mission.reward.thumbnail}
          reward={alert.mission.reward.itemString}
          credits={alert.mission.reward.credits}
          type={alert.mission.type}
          sector={alert.mission.node}
          key={alert.id}/>
          :null
    })}
  </main>
);
}

Next, in the component, I create a timer function to display time once.

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`
}

Finally, within the render area, I render the return function

<figcaption>

   {timer()}

</figcaption>

This renders it once. If I do this...

{setInterval(timer(), 1000)}

The function doesn't work, and gives the wrong values. How do I make it give the right values?

Matiny
  • 179
  • 3
  • 13
  • `timer()` is called immediately at `setInterval(timer(), 1000)` – guest271314 Jan 21 '18 at 16:05
  • Check this https://stackoverflow.com/questions/48056256/calling-function-at-set-intervals-in-react-presentational-component/48056311#48056311, also instead of `setInverval(timer(), 1000)` you need to write `setInterval(timer, 1000)` – Shubham Khatri Jan 21 '18 at 16:10
  • Let me know if the duplicate question doesn't solve your problem – Shubham Khatri Jan 21 '18 at 16:11
  • 1
    @ShubhamKhatri _"also instead of `setInverval(timer(), 1000)` you need to write `setInterval(timer, 1000)`"_ Have you done so at your own Answer at the linked Question? – guest271314 Jan 21 '18 at 16:14
  • @ShubhamKhatri I switched the return statement to setState. Now the values aren't changing, but the setinterval is causing a lot of CPU usage. I tried to avoid that in the 1st place by using return values, since the high CPU usage ruins the ajax auto update, and causes it to stop working. – Matiny Jan 21 '18 at 16:25
  • Also, setInterval(timer, 1000) gives the same result as using the parentheses. – Matiny Jan 21 '18 at 16:26
  • @guest271314, It was typo that I missed – Shubham Khatri Jan 21 '18 at 16:32
  • @Matiny What do you mean by "The function doesn't work, and gives the wrong values"? Instead of using `setInterval` and `setTimeout` you can use `EventSource` to stream data to the client from the server. – guest271314 Jan 21 '18 at 16:34
  • I'll be sure to learn how. Thanks. – Matiny Jan 21 '18 at 16:45
  • @Matiny, after setting state in timer, you need to render the state value, also setInterval shouldn't be a part of render but componentDidMount lifecycle method – Shubham Khatri Jan 21 '18 at 16:45
  • I can always set the state from componentDidMount, but when I did that it rendered a series of numbers for each component into one state. That's b/c I'm rendering the components based off map (meaning that it renders 2 to 5 at once). How do I set the individual timers from each component in a unique way? – Matiny Jan 21 '18 at 17:52

0 Answers0