accelerate accelerate - 3 months ago 17
React JSX Question

ReactJS fetching new data on prop

As a preface, I'm still new to React, so I'm still fumbling my way through things.

What I have is a component that fetches data to render an HTML table. So I call my Actions'

fetchData()
(which uses the browser's
fetch()
API) from within
componentWillMount()
, which also has a listener for a Store change. This all works well and good, and I'm able to retrieve and render data.

Now the next step. I want to be able to fetch new data when the component's props is updated. But I'm not exactly sure what the proper way to do so is. So I have a three part question


  1. Would the proper place to do my
    fetchData()
    on new props be in
    componentWillReceiveProps()
    , after validating that the props did change, of course?

  2. My API is rather slow, so it's entirely possible a new prop comes in while a fetch is still running. Is it possible to cancel the old fetch and start a new one, or at least implement logic to ignore the original result and wait for the results from the newer fetch?

  3. Related to the above question, is there a way to ensure only one fetch is running at any time besides having something like an
    isLoading
    boolean in my Action's state (or elsewhere)?


Answer

Yes, componentWillReceiveProps is the proper place to do that.

Regarding point 2 and 3:

The idea of cancelling the task and maintaining 'one fetch running' seems to be inadequate. I don't think this kind of solution should be used in any system because implementation would limit an efficiency of your app by design.

Is it possible to cancel the old fetch and start a new one, or at least implement logic to ignore the original result and wait for the results from the newer fetch?

Why don't you let a 'newer fetch' response override an 'old fetch' response?

If you really want to avoid displaying the old response you can implement it simply using a counter of all fetchData calls. You can implement it in this way:

var ApiClient = {
    processing: 0,
    fetchData: function(){
        processing++
        return yourLibForHTTPCall.get('http://endpoint').then(function (response)){
            processing--
            return response
        }
    },
    isIdle: function(){
        return processing == 0
    }   
}

and the place where you actually make a call:

apiClient.fetchData(function(response){
    if(apiClient.isIdle()){
        this.setState({
      })
    }
}

I hope yourLibForHTTPCall.get returns a Promise in your case.

Comments