Strange error with apollo/react-hooks, question about apollo versions

Is apollo/react-hooks the recommended package to use now? Because I know there’s also a 3rd party package that has a lot of stars. Do I need the latest apollo-client and apollo-react? I noticed there’s some “beta” and “alpha” tags so I was wondering what are the most recommended packages.

One of the errors I’m getting is a: Network error: null is not an object (evaluating ‘row[OBJECT_COLUMN_NAME] = key’
and I have no idea where it’s coming from or why it started happening to me.

I have another error with a similar useQuery hook where my entire expo app restarts.

The documentation says to use these packages but I’m wondering if it’s actually stable and tested thoroughly.

The Apollo GraphQL packages are all very reliable and in production at AirBnB, Expedia, the NY Times, etc.

I found the problem. It was because my query format. This format doesn’t work:

const QUERY = gql`
  query {
    getFoo{
      ...
    }
  }
`;

Also without the query doesn’t work

const QUERY = gql`
  {
    getFoo {
      ...
    }
  }
`;

But the worst part is that it was working, but later it produced this really cryptic error.

And by the way, this is the way it was in the documentation (the second example).

so it has to be like this:

const QUERY = gql`
  query getFoo {
    getFoo {
      ...
    }
  }
`;

I still don’t understand why Apollo forces you to use this longhand format, and why it can’t parse a simple query correctly, or give a reasonable error message at least.

Well, clearly these big companies have been able to work around all the warts. It’s easier when you have large budgets.

the query without name should work, but the named query is preferred, it makes your life easier when:

  • using apollo dev tools
  • use apollo to create typescript-types for your queries. seriously, this is a killer feature especially when using hooks!
1 Like

Thanks @macrozone. Do you know any good example projects or tutorial that is using hooks with typescript-types?

Basically like this:

// in your component or another hook:

import { useQuery } from "@apollo/react-hooks";
import gql from "graphql-tag";
import { YourQuery, YourQueryVariables } from "./types/YourQuery"; // these will get generated later...

// ...
const QUERY = gql`
  query YourQuery($variableX: String!) {
    someQuery(variableX: $variableX) {
      id
      whatever
      stuff {
        niceStuff
      }
    }
  }
`;
const variableX = "whatever";
const {data, loading, error} = useQuery<YourQuery, YourQueryVariables>(QUERY, { variables: { variableX } })
// data is type-safe! also variables are type safe! (when types are generated)

and then you can generate types from YourQuery with npx apollo codegen. I am not 100% what you exactly need, but that’s what we have in our package.json:

"scripts": {
   
    "graphql:schema-download": "npx apollo schema:download --endpoint=http://localhost:4000/graphql ./src/graphql-schema.json",
  "generate:types": "yarn graphql:schema-download && npx apollo codegen:generate --localSchemaFile=./src/graphql-schema.json --target=typescript --includes=\"src/**/*.{tsx,ts}\" --tagName=gql --globalTypesFile=src/types/global-types.ts types",
    
   
}

then you can invoke yarn generate:types (or npm run generate:types) to generate the types. Make sure to adjust http://localhost:4000/graphql to your needs. it assumes that http://localhost:4000/graphql is running locally

1 Like

Thanks @macrozone, cool.

Before I go down the rabbit hole of adding Typescript to my project, I wonder what kind of errors does this additional typing catch? I wonder if it catches errors at a) compile time b) app start c) runtime ?

typescript catches errors at compile time

Ok, I can see how it can validate the variables passed to the query. But I don’t see if or how it could validate the types returned by the query since Typescript doesn’t know GraphQL. But That would be a neat trick, or tool someone could make.

as descibe above, apollo codegen:generate will create typescript types based on your queries. You don’t validate the types returned by the query. Your types ARE defined by the query.

so e.g.


const QUERY = gql`
  query YourQuery($variableX: String!) {
    someQuery(variableX: $variableX) {
      id
      whatever
      stuff {
        niceStuff
      }
    }
  }
`;
const variableX = "whatever";
const {data, loading, error} = useQuery<YourQuery, YourQueryVariables>(QUERY, { variables: { variableX } })

 // this works and whatever will be a string, number or boolean, depending on the graphql type of whatever
// and yes, optional chaining (?.) works with latest typescript!

const whatever = data?.someQuery?.whatever

// this is a type error:
const something = data?.someQuery?.thisDoesNotExistOnTheQuery

The cool thing is, that you pass the return value of useQuery around without annotate it. You can also wrap it into its own hook.

As you mostly try to fetch as few properties as possible, this is very useful, because you will immediatly notice if you remove a property from the query that you still use somewhere in your application. Also you will notice if the graphql-backend has a breaking change (if you rerun apollo schema:download). I additionally recommend to use the vscode apollo plugin, so that you also can autocomplete and checking your grapqhl-query-strings

1 Like

That’s awesome. Thanks!