1

i have a comments connection in a mutation, this is the query:

    export default mutationFromQuery(graphql`
  mutation AddBookMutation($input: AddBookInput! $count: Int $cursor: String ) {
    addBook(input: $input) {
      book {
        __typename
        cursor
        node {
          id
          title
          owner
          createdAt
          comments(first: $count, after: $cursor)
          @connection(key: "BookComments_comments", filters: []) {
            __typename
            edges { 
              node { 
                id
              }
            }
          }
        }
      }
    }
  }
`)

This is how i did my optimisticUpdater that don't work:

optimisticUpdater: (store) => {
  const userProxy = store.get(viewerId)
  const owner = userProxy.getValue('username')
  const id = uuidv1();
  const book = store.create(id, 'Book');
  book.setValue(id, 'id');
  book.setValue(bookTitle, 'title');
  book.setValue(owner, 'owner');
  book.setValue(Date.now(), 'createdAt');
  const comments = store.create(uuidv1(), 'comments')
  comments.setLinkedRecords([], 'edges')
  const pageInfo = store.create(uuidv1(), 'pageInfo')
  pageInfo.setValue(null, 'endCursor')
  pageInfo.setValue(false, 'hasNextPage')
  pageInfo.setValue(false, 'hasPreviousPage')
  pageInfo.setValue(null, 'startCursor')
  comments.setLinkedRecord(pageInfo, 'pageInfo')
  book.setLinkedRecord(comments, 'comments')
  const bookEdge = store.create(uuidv1(), 'BookEdge');
  bookEdge.setLinkedRecord(book, 'node');
  console.log('bookEdge ', bookEdge)
  booksUpdater(userProxy, bookEdge);
},

The problem i have is that comments always ends up on undefined as you can see above i've already set it. I also did this but i am still not getting an optimistic UI:

    optimisticResponse: {
      addBook: {
        book: {
          __typename: 'BookEdge',
          cursor: uuidv1(),
          node: {
            id: uuidv1(),
            title: bookTitle,
            owner: username,
            createdAt: Date.now(),
            comments: {
              __typename: 'CommentConnection',
              edges: [],
              pageInfo: {
                endCursor: null,
                hasNextPage: false
              }
            }
          }
        }
      }
    },

App don't crash with optimisticResponse code but no optimistic UI effect, but with the optimisticUpdater it's crashing with comments being undefined, for now I am settling with my updater:

updater: (store) => {
   const userProxy = store.get(viewerId)
   const payload = store.getRootField('addBook');
   booksUpdater(userProxy, payload.getLinkedRecord('book'));
},

since the comments is undefined I guess we cannot use this for optimistic effect:

  const comments = store.create(uuidv1(), 'comments')
  comments.setLinkedRecords([], 'edges')
  book.setLinkedRecord(comments, 'comments')

on my Book, this is the query which has the comments fragment that is undefined on optimistic update with the code above:

export default createRefetchContainer(
  BookItem,
  {
    book: graphql`
      fragment BookItem_book on Book
        @argumentDefinitions(
          count: { type: "Int", defaultValue: 5 }
          cursor: { type: "String", defaultValue: null }
        ) {
        id
        title
        owner
        createdAt
        ...BookComments_book  
      }
    `
  },
  graphql`
    query BookItemQuery($id: ID!, $count: Int, $cursor: String) {
      book: node(id: $id) {
        ...BookItem_book @arguments(count: $count, cursor: $cursor)
      }
    }
  `
);

and now the query for the comments component where it gets the book.comments.edges is undefined:

export default createPaginationContainer(
  BookComments,
  {
    book: graphql`
      fragment BookComments_book on Book 
      @argumentDefinitions(
        count: { type: "Int", defaultValue: 3 }
        cursor: { type: "String", defaultValue: null }
      ) {
        id
        title
        comments(first: $count, after: $cursor)
          @connection(key: "BookComments_comments", filters: []) {
            __typename
          edges {
            node {
              id
              text
              owner
              createdAt
            }
          }
          pageInfo {
            startCursor
            endCursor
            hasPreviousPage
            hasNextPage
          }
        }
      }
    `
  },
  {
    direction: 'forward',
    getConnectionFromProps: (props) => props.book && props.book.comments,
    getFragmentVariables: (prevVars, totalCount) => ({
      ...prevVars,
      count: totalCount
    }),
    getVariables: (props, { count, cursor }, _fragmentVariables) => ({
      count,
      cursor,
      id: props.book.id
    }),
    query: graphql`
      query BookCommentsQuery($id: ID!, $count: Int, $cursor: String) {
        book: node(id: $id) {
          ...BookComments_book @arguments(count: $count, cursor: $cursor)
        }
      }
    `
  }
);

maybe this is an anti pattern? but i just wanted to have a optimistic effect for this

gpbaculio
  • 5,693
  • 13
  • 60
  • 102
  • post your full mutation code, and also all queries – Sibelius Seraphini Jul 12 '19 at 15:02
  • @SibeliusSeraphini i updated the question, getting comments is undefined in optimisticUpdater with this not working? => comments.setLinkedRecords([], 'edges') – gpbaculio Jul 12 '19 at 15:27
  • connection directive should be used in query or fragment, not in a mutation. Please post your query or fragment code that you use to fetch data that will be displayed in a component (that query is probably used in QueryRenderer or refetch container) – BorisTB Jul 12 '19 at 23:14
  • i only put that there cause I thought I tried everything and nothing works for optimistic for that comments nested connection so I'm just settling with my updater, you tried optimistic UI for a node with nested connection before? – gpbaculio Jul 13 '19 at 08:18
  • I always just handle empty/undefined nested connection in a component. I guess you want to optimistically add some comments, right? If not then it will be easier for you just to handle empty comments and wait until the real response comes from the server. – BorisTB Jul 13 '19 at 08:49
  • yes, that's why i did comments.setLinkedRecords([], 'edges') but I am getting an edges is undefined, maybe I can see your code? – gpbaculio Jul 13 '19 at 09:14
  • I think I can actually show you a complete solution, that you'll just copy paste into your code. The only thing I need is to see that query you use to fetch books – BorisTB Jul 13 '19 at 09:15
  • @Boris I just had the question updated. – gpbaculio Jul 13 '19 at 09:20
  • Oh sorry, I'll need one more thing. I see that mutation has AddBook in name, so it is probably used to create a new book. But in BookItemQuery you already fetching a book by id, so BookItem component is probably not the one where AddBook mutation is called or where you want to optimistically show new book. Sorry, I should have been more specific, but I need to see the query, that is going to be optimistically updated. I guess it's some list of books or something like that. – BorisTB Jul 13 '19 at 09:34

1 Answers1

1

Some things are still not very clear to me about how those components and queries work, so I'll update this answer later. (I don't know if you want to return new book optimistically from node() query or add it to some list/connection of books)

Please check if I used correct type names (CommentConnection / CommentsConnection, etc)

optimisticUpdater: (store) => {
  const userProxy = store.get(viewerId)
  const owner = userProxy.getValue('username')
  const commentsParams = {  // must be same keys and values as in comments(first: $count, after: $cursor)
    first: count,
    after: cursor
  }

  // Create Book
  const id = uuidv1();
  const book = store.create(id, 'Book');
  book.setValue(id, 'id');
  book.setValue(bookTitle, 'title');
  book.setValue(owner, 'owner');
  book.setValue(Date.now(), 'createdAt');

  // Create comments connection
  const comments = store.create(uuidv1(), 'CommentConnection')
  comments.setLinkedRecords([], 'edges')

  // Create PageInfo
  const pageInfo = store.create(uuidv1(), 'PageInfo')
  pageInfo.setValue(null, 'endCursor')
  pageInfo.setValue(false, 'hasNextPage')
  pageInfo.setValue(false, 'hasPreviousPage')
  pageInfo.setValue(null, 'startCursor')

  // Link created records
  comments.setLinkedRecord(pageInfo, 'pageInfo')
  book.setLinkedRecord(comments, 'comments', commentsParams) // don't forget commentsParams with same values as are used in comments graphql query

  // I'm not sure about this final part, because I don't really get how that app works, but if you want this book to show as optimistic response for `node(id: $id)`, you'll do something like this:
  store.getRoot().setLinkedRecord(book, 'node', { id: id }) // same id as used in BookItemQuery
}
BorisTB
  • 1,686
  • 1
  • 17
  • 26
  • i didn't know that there's arguments setting record(s), i digged it on docs and tried alot of things myself, still nothing worked, maybe you have tried doing mutation in nested connection? i was thinking of looking at your code and find out – gpbaculio Jul 14 '19 at 02:52