Help with Leaderboard React timing problem [SOLVED]

I’m having a timing issue in the Free Code Camp Leaderboard project.

It’s working fine if you click on the headers to sort by recent or alltime and wait for the request to finish.

If you click on alltime then back to recent really fast, it keeps listing the alltime users and remains inconsistent. Works that way vice-versa as well.

Any idea how I can track this bug, please? I’d appreciate any help.

I’m using componentDidMount and componentDidUpdate for the ajax calls.

The code is live at:

Thank you very much!

I think I did mine differently. I only did the ajax call once, when the program loaded. I worked on the assumption that the leader board wasn’t going to be changing minute by minute. I just loaded the data once and sorted by that. I don’t think there is a need to check if it has changed in the last 4 seconds.

If you really, really want to do that, you could perhaps disable the sorting buttons while a fetch is taking place. Or you can put logic in to the fetchUsers() so it won’t run if a fetch in progress, like create a boolean variable in the state, like isFetching and set it to true when you enter fetchUsers() and reset it to false in the callback to the fetch. Then when you first enter fetchUsers() you can check to see if it is set.

There might be a smarter way to do it, but that should work. But again, I don’t see any reason to fetch that data more than once.

1 Like

Hi @ksjazzguitar,

I ended up doing both things you suggested: putting the logic for a loading state in fetchUsers() to avoid making a request when one is already under way, and using the same loading value in the render method to disable the link while waiting for the request to arrive.

That solved the problem, so thank you for the suggestions!

I still don’t understand exactly what was causing the problem in the first place, so if you have tips or tools on how to track down stuff like this in the future I’d love to hear them.

About making the request only when the application loads: you mean you make both requests, that is, for recent and for alltime, in the beginning, then only switch between them in the UI? That seems like a good idea.

One thing to watch out for is that if you make only one request in the beginning, you get only one set of users right. For example:

  1. you make the request for recent
  2. the user clicks alltime
  3. you just sort the array in javascript by the alltime property

If you do that, you’ll only get the top recent users sorted by alltime, not the true overall alltime. For instance, if the number 1 alltime user hasn’t been active in the past 30 days, she won’t show up at all.

In my state I have a variable:

      campers: { alltime: [], recent: [] }

It is two arrays of users. I make two ajax calls to fill them up with the relevant data. Then, depending on which is selected, I map through the relevant array by selecting it. In my CamperList component I have the line:

{ this.props.campers[this.props.sort].map(function(camper, i) { return ( <Camper camper={camper} i={i}/> ) }) }

Where this.props.sort tells it which array to use and the component Camper creates the li for each camper that is mapped out inside the ul in CamperList.

So it’s two completely separate sets of data and React will map the correct one, whichever value this.props.sort is set to, either “alltime” or “recent”.

1 Like