Skip to content
This repository has been archived by the owner on Jul 10, 2019. It is now read-only.

Client mutation failed to update (array of objects with different shapes) #333

Open
sonlexqt opened this issue Dec 4, 2018 · 0 comments

Comments

@sonlexqt
Copy link

sonlexqt commented Dec 4, 2018

Hi, I'm using apollo-link-state to manage local state in my react-native app. Recently I face this frustrating issue:
Here's my app's defaults state:

const defaults = {
  language: 'en',
  user: null,
  conversation: {
    _id: null,
    users: [
      {
        userId: 'userA',
        quickReply: {
          type: 'NONE',
          payload: null,
        },
      },
      {
        userId: 'userB',
        quickReply: {
          type: 'NONE',
          payload: null,
        },
      },
    ],
  },
};

Here's the types definition:

type QuickReply {
  type: String
  payload: QuickReplyPayload
}
  
type UserInConversation {
  # other fields that I stripped out for clarity
  userId: String
  quickReply: QuickReply
}
  
type QuickReplyPayload {
  messageId: String
  conversationId: String
}

type Conversation {
  _id: String
  users: [UserInConversation]
  createdAt: Int
}

The client mutation:

const gqlSetConversationMutationClient = gql`
  mutation setConversation($conversation: Conversation!) {
    setConversation(conversation: $conversation) @client
  }
`;

The mutation's resolver:

setConversation: async (parent, { conversation }, { cache }, info) => {
      try {
        await cache.writeData({
          data: {
            conversation,
          },
        });
        return null;
      } catch (error) {
        console.log('ERROR - setConversation');
        console.log(error);
      }
    },

The client query to read conversation data from local state:

export const gqlConversationQueryClient = gql`
  query getConversation {
    conversation @client {
      _id
      users {
        userId
        quickReply {
          type
          payload {
            messageId
            conversationId
          }
        }
      }
    }
  }
`;

The issue I'm having here is that when I call setConversation, if the input conversation contains users objects with different payload shapes, the cache update will fail silently (error is not cached) and value of conversation in local state is set to undefined !!!
For example, with these conversation inputs:

// Both payload is null
const conversation1 = {
  _id: 'conversation1',
  users: [
    {
      userId: 'userA',
      quickReply: {
        type: 'NONE',
        payload: null,
      },
    },
    {
      userId: 'userB',
      quickReply: {
        type: 'NONE',
        payload: null,
      },
    },
  ],
}
// In this case I think the payload data is not in the same shape ?
// However it works !
const conversation2 = {
  _id: 'conversation2',
  users: [
    {
      userId: 'userA',
      quickReply: {
        type: 'NONE',
        payload: {
          conversationId: 'test',
        },
      },
    },
    {
      userId: 'userB',
      quickReply: {
        type: 'NONE',
        payload: {
          messageId: 'test',
        },
      },
    },
  ],
};

... setConversation executes successfully. However, with these inputs: (notice the differences in the shapes of quickReply.payload)

// Different payload shapes
const conversation3 = {
  _id: 'conversation3',
  users: [
    {
      userId: 'userA',
      quickReply: {
        type: 'NONE',
        payload: {},
      },
    },
    {
      userId: 'userB',
      quickReply: {
        type: 'NONE',
        payload: {
          messageId: 'test',
        },
      },
    },
  ],
};
// Different payload shapes
const conversation4 = {
  _id: 'conversation4',
  users: [
    {
      userId: 'userA',
      quickReply: {
        type: 'NONE',
        payload: null,
      },
    },
    {
      userId: 'userB',
      quickReply: {
        type: 'NONE',
        payload: {
          messageId: 'test',
        },
      },
    },
  ],
};

... setConversation will failed to execute, with no errors thrown, also it set the conversation value in local state to undefined, which breaks a lot of logic in my app.
My current work around for this is in the graphql server, I have a transformation function to always return the payload object in the shape of { messageId: '', conversationId: '' }.

Are there something wrong in my code or is this an issue with apollo link state ?

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

No branches or pull requests

1 participant