apollo-client: Query data and error are undefined

Intended outcome: I’m using useQuery to query and render some data. The loading prop works as expected, the value is true and then changes to false. When loading is false, data and error are both undefined.

I checked the network tab and the data is being received (I see the data prop)

Screen Shot 2021-04-27 at 1 41 51 PM

I also checked what’s going on with the Apollo chrome extension and I can see the data

Screen Shot 2021-04-27 at 1 34 24 PM Screen Shot 2021-04-27 at 1 34 10 PM

I also was able to verify the correct result from the BE using the fetch API

Screen Shot 2021-04-27 at 1 34 47 PM

Actual outcome: data and error props from useQuery are undefined.

How to reproduce the issue:

Here’s the component that uses useQuery and fetch

const QUERY = gql`
  query AccountStatus {
    accountStatus {
      __typename
      missingCode
      completed
      reason
    }
  }
`

const MissingThings = () => {
  const x = useQuery(QUERY)

  const { loading, data, error } = x

  console.log('--x', x)

  useEffect(() => {
    fetch(`${process.env.REACT_APP_GRAPHQL_URL}`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization:
          'Bearer <TOKEN>',
      },
      body: JSON.stringify({
        variables: {},
        query: `
        query AccountStatus {
          accountStatus {
            __typename
            missingCode
            completed
            reason
          }
        }
        
        `,
      }),
    })
      .then((result) => result.json())
      .then((result) => console.log('--result', result))
      .catch(console.error)
  }, [])

  if (loading) {
    return null
  }

  if (error) {
    console.log('--error', error)
    return null
  }

  console.log('--data', data)

  return <div>All good</div>
}

And this is the Apollo Client

const ApolloClientProvider = ({ children }: any) => {
  const { auth, account } = useGlobalProvider()
  const headers =
    auth && account ? { Authorization: `Bearer ${auth?.token}` } : {}

  console.log('--headers', headers)
  console.log('--auth', auth)

  const wsLink = new WebSocketLink({
    uri: process.env.REACT_APP_GRAPHQL_WS_URL as string,
    options: {
      reconnect: true,
      connectionParams: () => ({
        headers,
      }),
    },
  })

  const httpLink = new HttpLink({ uri: process.env.REACT_APP_GRAPHQL_URL })

  const authMiddleware = new ApolloLink((operation, forward) => {
    // add the authorization to the headers
    operation.setContext({
      headers:
        auth && account ? { Authorization: `Bearer ${auth?.token}` } : {},
    })

    return forward(operation)
  })

  const splitLink = split(
    ({ query }) => {
      const definition = getMainDefinition(query)
      return (
        definition.kind === 'OperationDefinition' &&
        definition.operation === 'subscription'
      )
    },
    wsLink,
    httpLink,
  )

  const logoutLink = onError((error) => {
    console.log('APOLLO ERROR!', error)

    if (
      error.networkError?.message.includes('JWTExpired') ||
      error.graphQLErrors?.some(
        ({ extensions, message }) =>
          extensions?.code === 'invalid-jwt' || message.includes('JWTExpired'),
      )
    ) {
      navigate('/logout')
    }
  })

  const client = new ApolloClient({
    cache: new InMemoryCache(),
    link: ApolloLink.from([logoutLink, authMiddleware, splitLink]),
  })

  return <ApolloProvider client={client}>{children}</ApolloProvider>
}

Versions System: OS: macOS 11.2.3 Binaries: Node: 14.8.0 - ~/n/bin/node npm: 6.14.7 - ~/n/bin/npm Browsers: Chrome: 90.0.4430.72 Safari: 14.0.3 npmPackages: @apollo/client: ^3.3.15 => 3.3.15

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 35
  • Comments: 45 (7 by maintainers)

Commits related to this issue

Most upvoted comments

Why is this closed?

I’m having the same bug of data being undefined but when backgrounding my app and foregrounding it. Verified via flipper that the data was actually coming in though. Setting fetchPolicy: network-only didnt solve it for my case.

    "@apollo/client": "^3.3.15",
    "react-native": "0.63.2",
    "apollo3-cache-persist": "^0.9.1",

This should be resolved in @apollo/client@latest - let us know if not.

I’ve tried every suggestion in this post and many other sources and most of the apollo client versions that people said worked and the problem is present 100% of the time. My schema and query are as simple as possible. The data shape matches perfectly. ** The correct data is clearly being returned during the fetch. ** I’ve tried everything possible. The client is getting good data back from the server. I tried the no-cache setting and the partial data setting and saw no improvement. The Loading feature seems to work fine, but I get the UNDEFINED error and UNDEFINED data at the end. I was never able to get Apollo to work and tried 4 or 5 fresh passes at all code from server to client, schema to model. It’s obviously something going sideways in the client at the final stage of handing the data to the caller. Regarding the cache, I can only say the setting had no effect and I would not have had cached data in all cases of the failure, which for me was 100%.

I’m seeing the same thing (@apollo/client 3.5. 10):

useQuery returns undefined for error and data, though I can see that loading is true at some point.

We both consume and provide the GraphQL API, so I have full ability to debug on both ends. The network response is exactly as we’d expect. Notably, there are no errors in the network response; the shape of the response is exactly as we’d expected, with the queried object nested under data.

For now, we’ve downgraded back to 3.2.5 to resolve this.

@jasongaare

If you are both the provider and consumer of the GraphQL API, this issue is occurring because the field structure of the query and the response do not match, which is usually due to the backend omitting a null field entirely instead of returning null for a null field. Example:

// => request
query {
  id
  name
}

// <= response
data: {
  id: 'asdf'
  // should be name: null
}

Otherwise, if you are only the consumer of the GraphQL API, you’re unfortunately out of other options until this issue is resolved.

@brainkim I believe you’re right. The useQuery hook is silently failing when the response doesn’t match the query exactly, but the response has a corresponding cache entry.

It would be nice to produce some kind of console warning or emit an error when this happens to prevent future confusion. I can take a further look at this later tonight.

I continued testing and I found out that not using the cache works:

const x = useQuery(QUERY, {
    fetchPolicy: 'network-only',
  })

Any idea of how to debug the cache? I see that the data is cached but Apollo is having a hard time retrieving it (that’s my conclusion)

Screen Shot 2021-04-27 at 2 03 35 PM

Running into this problem on 3.7.1

First query gives undefined for data and error. Response of 200 with expected data can be seen in the network.

Still encountering this problem.

Confirmed the same on version 3.80 and 3.8.1. Downgrading is also not an option for me.

Same issue for me on 3.6.9 I get the error on the first load of the query. Then if I reload the page, the error from the hook is undefined but I can still see it in the network 😞

I’m a little shocked this is still a thing, it only worked on 3.3.7 for me, not even 3.5.10.

it seems I was able to solve the problem!

If your server responds with a status other than 200, then “data” becomes “undefined” Example:

response.status(403)
return {message: "not authorized"}

data (client) = undefined

response.status(200)
(default 200)
return {message: "not authorized"}

data (client) = data{message: “not authorized”}

I hope this helps someone, good luck!

I’ve also encountered this issue, and setting fetchPolicy: network-only is not fixing it.

The oddest thing is that when I’m on a page where an object is queried for some fields, and then I open a component where the same object is queried for different fields, it is WORKING.

However, when I’m on a page that doesn’t contain any graphql query, and I open the same component that queries the object, the issue happens. In the network tab in dev tools the API actually returned the right data, but in the code where I did await client.query I got undefined.

I’ve tried to add ID to each of the object and subobjects and pass in fetchPolicy: no-cache or fetchPolicy: network-only, but nothing works.

I’m not doing watchQuery so returnPartialData is not an option.

The component is rendered by ReactDOM.render. I’ve checked appollo dev tool, and the data from this component is not appearing in the dev tool no matter the data shows correctly in UI or not (for both cases mentioned above). In the meanwhile, another graphql call in the page shows in the cache.

Hello, I’m experiencing this same issue, however I am not mocking anything.

As @brainkim suggested above, adding returnPartialData allows my useQuery hook to work again and properly return data. However, I’m not keen on adding that to all my queries with caching involved?

Is there somewhere in the cache setup where this can be addressed? Or what long term solution could I implement that doesn’t involve adding the returnPartialData option to all my useQuery hooks?

@diracs-delta This is a beautiful example. I’m dropping everything to investigate.

I was able to reproduce this issue on a separate repository. See below @brainkim

https://github.com/diracs-delta/apollo-client-8063