SF1
SF1

Reputation: 469

react: timing ajax request in render()

I've read a few similar questions but apparently no solutions.

I'm learning React and building an app which should connect to an API every 10/15 minutes. To connect, I am firing an ajax request. However I need the ajax request to be fired every 10 minutes therefore I'd need some sort of timer. If I call the method fetchData inside the render() method, the ajax request will be called every ~1 second. Even if I put a setTimeout() inside the render, this won't work with the ajax request (but it does work with other actions such as console.log()).

Any idea? Basically I need to continuously repeat the ajax request every 10 minutes without the user to click buttons or interact with the app. The first request should be fired when starting the app. Thanks!

fetchData = () => {

    var url = "http://url.json";
    $.ajax({
        url: url,
        dataType: "jsonp",
        success : this.parseResponse,
        error : function(req, err){ console.log('API call failed ' + err); }
    })
}

render(){
    //this.fetchData(); //this works but every 1 second
    setTimeout(() => {
        //this.fetchData(); //this won't work as expected
        console.log("timer"); //this works as expected
    }, 5000)

    return(
        <div>
            <button onClick={this.fetchData}></button> //this works as expected but I don't want this
        </div>
        );
}

Upvotes: 0

Views: 2617

Answers (2)

Arnold Gandarillas
Arnold Gandarillas

Reputation: 4322

First you need to know that if you are going to interact with an api you need to make the call in the componentDidMount method it's a recommended practice.

Then for make a continuous call you should use setInterval instead of setTimeout.

fetchData = () => {
  var url = "http://url.json";
  $.ajax({
    url: url,
    dataType: "jsonp",
    success: this.parseResponse,
    error: function (req, err) {
      console.log('API call failed ' + err);
    }
  })
}
componentDidMount () {
  // This will be called just once
  this.fetchData()

  this.interval = setInterval(() => {
    this.fetchData()
  }, 10000)
}
componentWillUnmount () {
  // It's necessary to do this otherwise the interval
  // will be executed even if the component is not present anymore. 
  clearInterval(this.interval);
}
render () {
  return (
    <div>
      ...
    </div>
  )
}

If you call fetchData inside the render method you are running the risk of entering in an infinite loop because if you update the state when the ajax is done (or for any reason) then the render will be executed and the fetchData method too so this will happen over and over again and to make it worst fetchData will be executed in intervals.

Upvotes: 4

Joshua R.
Joshua R.

Reputation: 2302

Why don't you call your setTimeout (or setInterval) in componentDidMount, which only fires once when the component is added to the DOM? In your render method, you're going to setTimeout every time there's a render, which could potentially be caused by other events than your fetch (though you haven't shown enough code to be sure).

Upvotes: 0

Related Questions