lfades / next-with-apollo

Apollo HOC for Next.js
MIT License
765 stars 78 forks source link

Can't find field X on object undefined #45

Closed EgidioCaprino closed 5 years ago

EgidioCaprino commented 5 years ago

Hi all,

I'm getting this error when using next-with-apollo in this project here.

I'm using the Query component rather than the graphql function.

GraphQL error occurred [getDataFromTree] { Error: Network error: Can't find field getCategories on object undefined.
    at new ApolloError (/home/egidio/Workspace/youvector/website/node_modules/apollo-client/bundle.umd.js:85:32)
    at /home/egidio/Workspace/youvector/website/node_modules/apollo-client/bundle.umd.js:1039:45
    at /home/egidio/Workspace/youvector/website/node_modules/apollo-client/bundle.umd.js:1411:21
    at Array.forEach (<anonymous>)
    at /home/egidio/Workspace/youvector/website/node_modules/apollo-client/bundle.umd.js:1410:22
    at Map.forEach (<anonymous>)
    at QueryManager.broadcastQueries (/home/egidio/Workspace/youvector/website/node_modules/apollo-client/bundle.umd.js:1405:26)
    at /home/egidio/Workspace/youvector/website/node_modules/apollo-client/bundle.umd.js:988:35
  graphQLErrors: [],
  networkError:
   Error: Can't find field getCategories on object undefined.
       at /home/egidio/Workspace/youvector/website/node_modules/aws-appsync/node_modules/apollo-cache-inmemory/lib/bundle.umd.js:429:27
       at Array.forEach (<anonymous>)
       at StoreReader.diffQueryAgainstStore (/home/egidio/Workspace/youvector/website/node_modules/aws-appsync/node_modules/apollo-cache-inmemory/lib/bundle.umd.js:426:36)
       at StoreReader.readQueryFromStore (/home/egidio/Workspace/youvector/website/node_modules/aws-appsync/node_modules/apollo-cache-inmemory/lib/bundle.umd.js:401:25)
       at processOfflineQuery (/home/egidio/Workspace/youvector/website/node_modules/aws-appsync/lib/link/offline-link.js:158:34)
       at /home/egidio/Workspace/youvector/website/node_modules/aws-appsync/lib/link/offline-link.js:114:28
       at new Subscription (/home/egidio/Workspace/youvector/website/node_modules/zen-observable/lib/Observable.js:183:34)
       at Observable.subscribe (/home/egidio/Workspace/youvector/website/node_modules/zen-observable/lib/Observable.js:262:14)
       at /home/egidio/Workspace/youvector/website/node_modules/aws-appsync/lib/client.js:175:67,
  message:
   "Network error: Can't find field getCategories on object undefined.",
  extraInfo: undefined }

That error is server-side. Data is fetched correctly on client-side. Is that the expected behaviour?

EgidioCaprino commented 5 years ago

@lfades can you help me?

lfades commented 5 years ago

That's not expected, can you try disabling SSR and see if it still happens ?, and if possible, is your code open source ?

EgidioCaprino commented 5 years ago

I've already tried to disable ssr but still getting the same issue. My project is here https://github.com/EgidioCaprino/youvector/blob/master/website/pages/index.js#L30

lfades commented 5 years ago

Can you move the query out of the component and try again ? it should not be there btw

EgidioCaprino commented 5 years ago

@lfades I've tried this but getting the same error as before

const query = gql`
  query($id: ID!) {
    getCategory(id: $id) {
      name
      description
      subCategories {
        name
        illustrations {
          id
          name
        }
      }
      parentCategory {
        id
      }
    }
  }
`;

export default withRouter(({ router }) => {
  const { id } = router.query;
  return (
    <Query query={query} variables={{ id }}>
      {({ loading, error, data }) => {
        if (error) {
          throw error;
        }
        if (loading) {
          return <Spinner />;
        }
        const category = data.getCategory;
        if (category.parentCategory && category.parentCategory.id) {
          // @todo this redirect is not working probably because of this https://github.com/lfades/next-with-apollo/issues/45
          Router.replace({
            href: '/category',
            query: { id: category.parentCategory.id },
          }).catch(() => {});
        }
        return <CategoryPage {...category} />;
      }}
    </Query>
  );
});

Btw, why should not the query be defined inside a component?

lfades commented 5 years ago

because gql will transform the query into an AST, it's not something to be done every render because it takes time, and it should be done once. If you do a console log of data in the query response, do you see undefined ?

EgidioCaprino commented 5 years ago

I've added this console.log

....
{({ loading, error, data }) => {
  console.log('data', data);
....

On client side it logs this

image

While on server side it logs this

image

Thanks for the heads up with gql. I'll look better into it :smiley:

lfades commented 5 years ago

Is that everything you are able to see ? I think that the issue may be with trying to do the request in the server with aws-appsync, I don't think that it just works out of the box without any special configuration for SSR, can you go to their docs and confirm that ?

EgidioCaprino commented 5 years ago

I was able to set it up correctly with next-apollo-appsync but that didn't work out with new components such <Query> and <Mutation> and I would ended up using the old graphql function. That's why I wanted to try your library, which I think it's pretty cool.

Unfortunately doesn't seem to bind very well with AppSync so I guess I should fall back on next-apollo-appsync.

lfades commented 5 years ago

Well, this is what you're missing: https://github.com/dabit3/next-apollo-appsync/blob/master/src/initApollo.js#L16

I can make a example that works for you, let me finish my breakfast first

EgidioCaprino commented 5 years ago

Thank you so much @lfades :heart:

This seems to have fixed the problem https://github.com/EgidioCaprino/youvector/commit/3e7a4b692059e013998e9131bfe186167ef3b4d4

lfades commented 5 years ago

Amazing, good work 👍 💃

lfades commented 5 years ago

Oh @EgidioCaprino btw you need to create the client inside the function, not outside, or you'll have a ton of problems because the client needs to be created always in SSR, and only be reused in the client.

EgidioCaprino commented 5 years ago

Do I need to do so even if my backend runs on a Lambda function in AWS? That is stateless and the connection would not be shared anyway, right?

lfades commented 5 years ago

Yes, even so, don't take the chance of having a memory leak.

EgidioCaprino commented 5 years ago

Alright, thanks @lfades :+1: