score:20

Accepted answer

I figured out my mistake, and it had nothing to do with React per se. It was a classic case of missing javascript closure inside a loop.

Because of the possibility of duplicates I stored each ajax response in window.localStorage, on the movieId. Or so I thought.

In React Inifinite Scroll each item in your list is drawn sequentially with a call to the loadMore-function. Inside this function I did my ajax call, and stored the result in the browser cache. The code looked something like this:

  var cachedValue = window.localStorage.getItem(String(movieId));
  var cachedData = cachedValue ? JSON.parse(cachedValue) : cachedValue;

  if (cachedData != null) {
    comp.drawNextMovie(cachedData);
  } else { 
    $.ajax( {
      type: "GET",
      url: this.state.movieUrl + movieId,
      contentType: "json",
      success: function (movieData) {
        window.localStorage.setItem(String(movieId), JSON.stringify(movieData));
        comp.drawNextMovie(movieData);
      }
    });  
  }    

Can you spot the mistake? When the ajax-call returns, movieId is no longer what is was. So I end up storing the data by the wrong id, and get some strange React warnings in return. Because this was done inside the loadMore function called by the InfiniteScroll-module, I was not aware that this function was not properly scoped.

I fixed it by adding a Immediately-invoked function expression.

score:12

I wouldn't use the ID from a back-end as key property in React. If you do, you're relying on some logic that's a bit far away from your component to make sure that your keys are unique. If they keys are not unique, you can break react's rendering so this is quite important.

This is why you should, in my opinion, just stick to using the index within a for loop or similar to set key properties. That way you know they can never be non-unique, and it's the simplest way of doing exactly that.

Without knowing exactly how your IDs work it's impossible to say what's causing the non-unique clash here. However since key is just to allow React to correctly identify elements, and nothing else, it doesn't really make sense for it to be anything other than a simple count or index.

var children = [];
for (var i=0; i<yourArray.length; i++) {
    children.push(
        <div key={i}>{yourArray[i].someProp}</div>
    );
}

Related Query

More Query from same tag