Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do optimistic updates respect array ordering? #1271

Closed
rgovindji opened this issue Jul 11, 2016 · 7 comments
Closed

Do optimistic updates respect array ordering? #1271

rgovindji opened this issue Jul 11, 2016 · 7 comments

Comments

@rgovindji
Copy link

I have an array of movies that are ordered by user rating. When the user changes the rating of one movie the ordering of the list is also changed. I created an optimistic update which re-orders the list appropriately but even tho Relay shows the optimistic response is in the correct order, in componentWillReceiveProps the order of the array remains the same even tho the rating ( 3 stars updated to 5 stars) has correctly changed. When the server replies back with the updated array, I see my listview refresh in the correct order.

How do I make sure that componentWillReceiveProps gets the ordered array that I generated in my optimistic update?

@jardakotesovec
Copy link
Contributor

jardakotesovec commented Jul 11, 2016

@rgovindji Can you share code of the mutation? Are you returning correct id of object that contains the list in optimistic update, so it knows which list to update? Wrong shape or missing id in optimistic update are my usual suspects for such behavior :-).

@rgovindji
Copy link
Author

Here's what I'm doing. The only ID I see on the array is a field named dataID is that what I'm supposed to add to the optimistic update?

getOptimisticResponse() {

    let selectedMovie = this.props.selectedMovie; // Updated movie
    let newRating = this.props.newRating; // New rating

    let length = this.props.favorites.movies.edges.length;
    let moviesArr = [];
    //create movies array for optimistic update
    for (let i = 0; i < length; i++) {
      let movie = this.props.favorites.movies.edges[i].node;
      let rating = movie.rating;

      //Update selected movies rating to new rating
      if (movie.id === selectedMovie.id) {
        rating = newRating;
      }

      //Push movie into array
      moviesArr.push({ node: { id: movie.id, rating: rating } });
    }

    // Sort the movies based on rating list
    moviesArr.sort((a, b) => { return a.node.rating > b.node.rating; });

    return {
      favorites: {
        id: this.props.favorites.id,
        movies: {
          edges: moviesArr
        }
      }
    };
  }

@jardakotesovec
Copy link
Contributor

@rgovindji I meant whole mutation, that could give more clues. I don't see any obvious issue with this..

@jardakotesovec
Copy link
Contributor

On the other hand I have not used optimistic updates with connections, just lists. So wondering if its also important to copy edge cursors so it gets applied in store.

@rgovindji
Copy link
Author

@jardakotesovec Here's the whole mutation. I'll try adding the cursor for each edge in the response to see if that works.

import Relay from 'react-relay';

export default class UpdateFavMovieRatingMutation extends Relay.Mutation {

  getMutation() {
    return Relay.QL`mutation{updateFavMovieRating}`;
  }

  getFatQuery() {
    return Relay.QL`
        fragment on updateFavMovieRatingPayload {
            favorites{
             id
             movies(first: 10 orderBy: RATING)
           }
        }
    `;
  }

  getConfigs() {
    return [{
      type: 'FIELDS_CHANGE',
      fieldIDs: {
        favorites: this.props.favorites.id
      }
    }];
  }

  getVariables() {
    return {
        movieId: this.props.selectedMovie.id,
        rating: this.props.newRating    
      };
  }

getOptimisticResponse() {

    let selectedMovie = this.props.selectedMovie; // Updated movie
    let newRating = this.props.newRating; // New rating

    let length = this.props.favorites.movies.edges.length;
    let moviesArr = [];
    //create movies array for optimistic update
    for (let i = 0; i < length; i++) {
      let movie = this.props.favorites.movies.edges[i].node;
      let rating = movie.rating;

      //Update selected movies rating to new rating
      if (movie.id === selectedMovie.id) {
        rating = newRating;
      }

      //Push movie into array
      moviesArr.push({ node: { id: movie.id, rating: rating } });
    }

    // Sort the movies based on rating list
    moviesArr.sort((a, b) => { return a.node.rating > b.node.rating; });

    return {
      favorites: {
        id: this.props.favorites.id,
        movies: {
          edges: moviesArr
        }
      }
    };
  }

}

@NevilleS
Copy link
Contributor

I'd expect this to work, so the likely issue here is that your optimistic response isn't quite right. Relay applies the optimistic response in a "best-effort" kind of way which means it basically never throws any errors to help figure out why it's not doing what you expect it to (which can be frustrating, I'm sure).

In this case, I suspect that the lack of cursors on your edge objects fools Relay's client-side type inference into treating this response as some kind of unknown list, and therefore doesn't update your connection like you hope it will. Adding cursors is probably the best bet, let us know if that doesn't help.

In general my advice for applying an optimistic response is to copy the "real" server response and then gradually delete fields from it and test to make sure it still updates your UI like you want it to. Once you remove enough fields to get an object you are confident you can generate client-side, write the code to do that.

@rgovindji
Copy link
Author

Adding cursors to the edges didn't work for me but I removed optimistic updates from my code for the moment. I like your suggestion of copying the real response and trimming the data down, I'll give that a shot when I have time.

I'm going to close the issue for now until I'm certain it's not a fault in my code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants