Search code examples
javascriptapollo

Apollo is returning data wrong, but is correct in Network inspector


I have a React/Apollo app that keeps getting my data garbled up and wrong. The data looks correct in the Network inspector, but when Apollo returns it, it changes it.

The records that come back should look something like:

{
  id: 12345,
  name: 'some record',
  status: { id: 1, name: 'Active' }
  types: [
    { id: 1, name: 'Client' },
    { id: 4, name: 'Example' }
  ],
  // ... more props
}

And they DO look like this when I look at the raw response in the Network inspector in Chrome.

The records that Apollo returns however, look like this:

{
  id: 12345,
  name: 'some record',
  status: { id: 1, name: 'Client' } // <-- The word "Active" gets changed to "Client"
  types: [
    { id: 1, name: 'Client' },
    { id: 4, name: 'Example' }
  ],
  // ... more props
}

I assume Apollo is trying to be all fancy and cool trying to "cache" records or something and it's assuming that the Status IDs and Type IDs are the same. So it's seeing the status.id being 1, so it assumes that's the same as the Type ID of 1.

How do I turn off all of Apollo's fancy stupid "features"?

Edit: Screenshots

This is the raw data printed from the console, the console.log of my useQuery hook data: enter image description here

This is the raw output that I see in the Network inspector: enter image description here

I have no explanation as to why these come out different other than Apollo doing some weird internal logic. It's literally correct in the response, but as soon as Apollo returns it to me it's different.

My code:

const { data, refetch } = useQuery(gql`
    query GetScoreAudit(
      $page: Int, $pageSize: Int, $search: String,
      $orderBy: String, $order: Order,
      $status: Int, $type: Int
    ) {
      scoreAudit(
        page: $page, pageSize: $pageSize, search: $search,
        orderBy: $orderBy, order: $order,
        status: $status, type: $type
      ) {
        total
        nodes {
          id
          name
          managedWorkstations
          managedServers
          firewall
          wpsCompliance
          maxWpsCompliance
          mrr
          tpe
          status {
            id
            name
          }
          types {
            id
            name
          }
          serviceCompanies {
            service
            exists
          }
        }
      }
    }
  `, {
    variables: {
      page: tableOpts.pagination.page,
      pageSize: tableOpts.pagination.pageSize,
      search: tableOpts.filters.search,
      orderBy: tableOpts.orderBy,
      order: tableOpts.order,
      status: tableOpts.filters.status,
      type: tableOpts.filters.type
    }
  });

  console.log(data);

Stringified output data: enter image description here


Solution

  • This is Apollo Client's normalized cache - you can (and probably should) read more about it in the documentation.

    Generally: if Apollo Client encounters two objects with the same combination of __typename:id, it considers them to be "the same object", stores them in the same place and merges them together.

    So in your case, both of these items have the "internal id" CWBaseRecord:1 - and the best thing you could do would be to make sure that your server actually returns different id/type combinations for things that are not the same.

    If you cannot do that, you could add a type policy for CWBaseRecord that states that they should not be normalized:

          const client = new ApolloClient({
            // ...
            cache: new InMemoryCache({
              typePolicies: {
                CWBaseRecord: {
                  keyFields: false,
                },
              },
            }),
          });