Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error in with-apollo example #3234

Closed
1 task done
f2net opened this issue Nov 3, 2017 · 8 comments
Closed
1 task done

Error in with-apollo example #3234

f2net opened this issue Nov 3, 2017 · 8 comments

Comments

@f2net
Copy link

f2net commented Nov 3, 2017

  • I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior

The expected behavior is that of the online demo.

Current Behavior

Unfortunately, when you clone the repo, npm install and run it gives an error when you navigate client-side to the Home:
TypeError: Cannot read property 'data' of undefined at new WithData (http://localhost:3000/_next/1509705233244/page/:19478:79)

Steps to Reproduce (for bugs)

The steps of the example installation guide:

  1. curl https://codeload.github.com/zeit/next.js/tar.gz/master | tar -xz --strip=2 next.js-master/examples/with-apollo
  2. cd with-apollo
  3. npm install
  4. npm run dev
  5. navigate from home to /about
  6. Navigate back to Home

Context

I tried to clone the repo because I found the issue on my project after upgrading to React Apollo 2 and copying the /lib code of the example (initApollo and withData).

On my project I see another issue: I see always the client-side network call even on refresh. I fear that it has to do with some confusion with Apollo 2 InMemoryCache, sometimes found imported from apollo-cache-inmemory and sometimes from apollo-client-preset.

Thank you,
Matteo

@t0ker
Copy link

t0ker commented Nov 3, 2017

replace serverstate in Withdata.js with this line:

let serverState = { apollo: {} };

this solves the issue :)

@f2net
Copy link
Author

f2net commented Nov 3, 2017

Thank you very much! This solves the problem indeed :)

Now I'll have to understand why on my project I see the data loaded by the client over the network, using the same initApollo and withData (I don't set any particular fetching policy, so it should default to cache as in the example) :S

@f2net
Copy link
Author

f2net commented Nov 3, 2017

I discovered the problem for the client-side fetching, but I open a specific issue for that.
I close this.

@f2net f2net closed this as completed Nov 3, 2017
ahalimkara added a commit to ahalimkara/next.js that referenced this issue Dec 15, 2017
timneutkens pushed a commit that referenced this issue Dec 18, 2017
timneutkens pushed a commit that referenced this issue Dec 19, 2017
* Update withData.js (#3458)

#3234

* Begun with-reflux example

* Built with-reflux example

* Built with-reflux example
@gcfabri
Copy link

gcfabri commented Mar 1, 2018

Please, help me. What am I doing wrong to get this error:
image

withData.js

import cookie from 'cookie';
import PropTypes from 'prop-types';
import Head from 'next/head';
import { ApolloProvider, getDataFromTree } from 'react-apollo';
import React from 'react';

import initApollo from './initApollo';

function parseCookie(ctx = {}, options = {}) {
  return cookie.parse(ctx.req && ctx.req.headers.cookie ? ctx.req.headers.cookie : document.cookie, options);
}

function getComponentDisplayName(Component) {
  return Component.displayName || Component.name || 'Unknown';
}

export default (ComposedComponent) => {
  return class WithData extends React.Component {
    static displayName = `WithData(${getComponentDisplayName(ComposedComponent)})`;
    static propTypes = {
      serverState: PropTypes.object.isRequired
    };

    static async getInitialProps(ctx) {
      let serverState = {
        apollo: {
          data: {}
        }
      };

      // Setup a server-side one-time-use apollo client for initial props and
      // rendering (on server)
      let apollo = initApollo({}, { getToken: () => parseCookie(ctx).jwt });

      // Evaluate the composed component's getInitialProps()
      let composedInitialProps = {};
      if (ComposedComponent.getInitialProps) {
        composedInitialProps = await ComposedComponent.getInitialProps(ctx, apollo);
      }

      // Run all graphql queries in the component tree
      // and extract the resulting data
      if (!process.browser) {
        if (ctx.res && ctx.res.finished) {
          // When redirecting, the response is finished.
          // No point in continuing to render
          return;
        }

        // Provide the `url` prop data in case a graphql query uses it
        const url = { query: ctx.query, pathname: ctx.pathname };
        try {
          // Run all GraphQL queries
          const app = (
            <ApolloProvider client={apollo}>
              <ComposedComponent url={url} {...composedInitialProps} />
            </ApolloProvider>
          );
          await getDataFromTree(app, {
            router: {
              query: ctx.query,
              pathname: ctx.pathname,
              asPath: ctx.asPath
            }
          });
        } catch (error) {
          // Prevent Apollo Client GraphQL errors from crashing SSR.
          // Handle them in components via the data.error prop:
          // http://dev.apollodata.com/react/api-queries.html#graphql-query-data-error
        }
        // getDataFromTree does not call componentWillUnmount
        // head side effect therefore need to be cleared manually
        Head.rewind();

        // Extract query data from the Apollo's store
        serverState = {
          apollo: {
            data: apollo.cache.extract()
          }
        };
      }

      return {
        serverState,
        ...composedInitialProps
      };
    }

    constructor(props) {
      super(props);
      // Note: Apollo should never be used on the server side beyond the initial
      // render within `getInitialProps()` above (since the entire prop tree
      // will be initialized there), meaning the below will only ever be
      // executed on the client.
      this.apollo = initApollo(this.props.serverState.apollo.data, {
        getToken: () => parseCookie()
      });
    }

    render() {
      return (
        <ApolloProvider client={this.apollo}>
          <ComposedComponent {...this.props} />
        </ApolloProvider>
      );
    }
  };
};

@markbrouch
Copy link

@gcfabri I was getting this error because I was wrapping a component with withData() instead of a page. Can anyone clarify why this is a problem?

@klujanrosas
Copy link
Contributor

klujanrosas commented May 9, 2018

@markbrouch I think it has something to do with getInitialProps not being executed in any other component that isn't a page(unless you pass them through, ofc)
Therefore getInitialProps will never be executed, and when rendering it will complain on accessing this.props.serverState.apollo.data because props wouldn't have a serverState key, nor any of the other composedInitialProps.
I might be wrong though.

@CaptainChemist
Copy link

@markbrouch @klujanrosas Did either of you figure out what the solution is for this? I'm trying to figure out how I can have the query built into the component itself so that it can be placed on any page. What does the getInitialProps need to be on a component if I want to wrap a withData() around it?

@Vadorequest
Copy link
Contributor

Vadorequest commented Apr 17, 2019

Meeting a similar issue on Next 5 (yeah, I know, outdated version)
I managed to make it work for a page, but I can't make it work for either the layout nor components.

For the record, I'm using https://github.com/adamsoffer/next-apollo-example which really simplifies the integration of apollo in nextjs

@lock lock bot locked as resolved and limited conversation to collaborators Apr 17, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants