apollo-client: @defer not working in React Native

Issue Description

When calling client.query({...}) in a redux action, this returns an error “Error: [TypeError: Cannot read property ‘length’ of undefined]” whenever @defer is used in the query.

For instance, giving a query like so:

const GET_USERS = gql`
  query users($first: Int, $last: int, $id: int) { // im using relay connection args in BE for pagination
    users(first: $first, last: $last, id: $id) {
       pageInfo {
         endCursor
       }
       edges {
         node {
           name
           image_url 
           ... @defer {
               subscriptions {
                  status
               }
            }
         }
       }
    }
  }
 `

And i have a redux action like so:

const getUsers = async () => {
   const response = await client.query({
     query: GET_USERS,
   })
 // application doesnt return a response or anything 
// simply returns Error:  [TypeError: Cannot read property 'length' of undefined] in console

 }

@apollo/server: “4.3.0” The reproduction repo doesnt currently use redux, but will add redux later today. Thought this is something the team may have seen before hence why I’m creating this. I can confirm @defer works just fine with useQuery. However, we’re using redux and abstracting apolloClient for use in all our actions which has always worked.

Link to Reproduction

https://github.com/bwoodlt/rn-apollo-client-testbed

Reproduction Steps

No response

@apollo/client version

3.9.2

About this issue

  • Original URL
  • State: closed
  • Created 5 months ago
  • Comments: 20 (11 by maintainers)

Most upvoted comments

@bwoodlt Great to hear that you found it! I’m sorry I couldn’t really help more here!

Took me a while to pull these together…

  • the query text expected by the server

Using the requestDidStart and didEncounterErrors plugins on the server, the client sends this for matches:

api_1-1  | [07/02/2024 16:01:48.946] [LOG]    errors_here: provided sha does not match query
api_1-1  | [07/02/2024 16:01:48.970] [LOG]    {
   'query getMatches($userId: Int!) {\n' +
     '  matches(user_id: $userId) {\n' +
     '    matchesId\n' +
    '    swipedByUser {\n' +
    '      user_id\n' +
    '      name\n' +
     '      image_url\n' +
     '      description\n' +
     '      city\n' +
    '      country\n' +
    '      __typename\n' +
     '    }\n' +
    '    swipedUser {\n' +
    '      user_id\n' +
    '      __typename\n' +
    '    }\n' +
    '    createdAt\n' +
    '    operationType\n' +
     '    __typename\n' +
    '  }\n' +
  '}'
 }
  • the hash for that query expected on the server
api_1-1  |     http: {
api_1-1  |       method: 'GET',
api_1-1  |       headers: [HeaderMap [Map]],
_api_1-1  |       search: '?operationName=getMatches&variables=%7B%22userId%22%3A002%7D&extensions=%7B%22persistedQuery%22%3A%7B%22version%22%3A1%2C%22sha256Hash%22%3A%2245c8cf69b6f71af947bdbf11370c4e303daaf848d7c83bf3049cf031bf308665%22%7D%7D',_
api_1-1  |       body: {}
api_1-1  |     }
  • the query text the client would send out (console.log it when calculating the hash)

The client doesnt actually show the query text, when you breakdown the query param, this is what you get, this is even with ApolloLink logging outgoing requests:

 INFO  request name getMatches
 INFO  request query [{"directives": [], "kind": "OperationDefinition", "name": {"kind": "Name", "value": "getMatches"}, "operation": "query", "selectionSet": {"kind": "SelectionSet", "selections": [Array]}, "variableDefinitions": [[Object]]}]
  • the hash that the client is sending out
LOG  {"query_name": "getMatches", "sha256Hash": "45c8cf69b6f71af947bdbf11370c4e303daaf848d7c83bf3049cf031bf308665"}

I noticed the hash expected with getMatches 2245c8cf69b6f71af947bdbf11370c4e303daaf848d7c83bf3049cf031bf308665 on the server is different from what client is sending i.e 45c8cf69b6f71af947bdbf11370c4e303daaf848d7c83bf3049cf031bf308665. The question is, how does it attach a different hash value and how do I obtain this if the client is expecting a hash function to be provided?