Git Product home page Git Product logo

next-with-apollo's Introduction

next-with-apollo

Actions Status

Apollo HOC for Next.js.

For Next v9 use the latest version.

For Next v6-v8 use the version 3.4.0.

For Next v5 and lower go here and use the version 1.0.

How to use

Install the package with npm:

npm install next-with-apollo

or with yarn:

yarn add next-with-apollo

Create the HOC using a basic setup and apollo-boost:

// lib/withApollo.js
import withApollo from 'next-with-apollo';
import ApolloClient, { InMemoryCache } from 'apollo-boost';
import { ApolloProvider } from '@apollo/react-hooks';

export default withApollo(
  ({ initialState }) => {
    return new ApolloClient({
      uri: 'https://mysite.com/graphql',
      cache: new InMemoryCache().restore(initialState || {})
    });
  },
  {
    render: ({ Page, props }) => {
      return (
        <ApolloProvider client={props.apollo}>
          <Page {...props} />
        </ApolloProvider>
      );
    }
  }
);

Note: apollo-boost is used in this example because is the fastest way to create an ApolloClient, but is not required.

Note: If using react-apollo, you will need to import the ApolloProvider from react-apollo instead of @apollo/react-hooks.

Now let's use lib/withApollo.js in one of our pages:

// pages/index.js
import gql from 'graphql-tag';
import { useQuery } from '@apollo/react-hooks';
import withApollo from '../lib/withApollo';
// import { getDataFromTree } from '@apollo/react-ssr';

const QUERY = gql`
  {
    title
  }
`;

const Index = () => {
  const { loading, data } = useQuery(QUERY);

  if (loading || !data) {
    return <h1>loading...</h1>;
  }
  return <h1>{data.title}</h1>;
};

export default withApollo(Index);

// You can also override the configs for withApollo here, so if you want
// this page to have SSR (and to be a lambda) for SEO purposes and remove
// the loading state, uncomment the import at the beginning and this:
//
// export default withApollo(Index, { getDataFromTree });

Now your page can use anything from @apollo/react-hooks or react-apollo. If you want to add Apollo in _app instead of per page, go to Using _app.

withApollo API

withApollo receives 2 parameters, the first one is a function that returns the Apollo Client, this function receives an object with the following properties:

  • ctx - This is the context object sent by Next.js to the getInitialProps of your page. It's only available for SSR, in the client it will be undefined
  • initialState - If getDataFromTree is sent, this will be the initial data required by the queries in your page, otherwise it will be undefined
  • headers - This is ctx.req.headers, in the client it will be undefined
  • router - This is the router object sent by getInitialProps. Only available in the server and when using getInitialProps

The second, optional parameter, received by withApollo, is an object with the following props:

  • render - A function that receives an object ({ Page, props }) with the current Page Component to be rendered, and its props. It can be used to wrap your pages with <ApolloProvider>. It's optional
  • getDataFromTree - implementation of getDataFromTree, defaults to undefined. It's recommended to never set this prop, otherwise the page will be a lambda without Automatic Static Optimization
  • onError - A function that will be called if getDataFromTree encounters errors. If not supplied errors will be silently ignored. It will be called with 2 parameters:

Using getInitialProps

Pages with getInitialProps can access the Apollo Client like so:

Page.getInitialProps = ctx => {
  const apolloClient = ctx.apolloClient;
};

Next.js applies very good optimizations by default, including Automatic Static Optimization, and as long as the getDataFromTree config is not added, your pages will always be static and can be served directly from a CDN, instead of having a serverless function being executed for every new request, which is also more expensive.

If your page has getDataFromTree to remove the loading states of Apollo Queries, you should consider handling the loading states by yourself, fetching all queries per request and before sending the initial HTML will slow down the first render, and the user may end up waiting a long time without any feedback.

Using _app

If you want to add Apollo to all pages, you can use pages/_app.js, like so:

import withApollo from 'next-with-apollo';
import { ApolloProvider } from '@apollo/react-hooks';
import ApolloClient, { InMemoryCache } from 'apollo-boost';

const App = ({ Component, pageProps, apollo }) => (
  <ApolloProvider client={apollo}>
    <Component {...pageProps} />
  </ApolloProvider>
);

export default withApollo(({ initialState }) => {
  return new ApolloClient({
    uri: 'https://mysite.com/graphql',
    cache: new InMemoryCache().restore(initialState || {})
  });
})(App);

It's better to add Apollo in every page instead if you have pages that don't need Apollo.

To access Apollo Client in each page's getInitialProps, add getInitialProps to App like so:

import App from 'next/app';

MyApp.getInitialProps = async appContext => {
  const appProps = await App.getInitialProps(appContext);
  return { ...appProps };
};

If you either add the getDataFromTree config or getInitialProps, it will turn all pages into lambdas and disable Automatic Static Optimization.

Migration guide

from 4.3.0 to 5.0.0

In 4.3.0 all the queries where fetched on server by default (getDataFromTree option was set to 'always' by default). In order to get the same behaviour in 5.0.0 you need to explicitly pass getDataFromTree (from @apollo/react-ssr) to withApollo.

next-with-apollo's People

Contributors

9renpoto avatar alexmunoz avatar alinazariii avatar anthonyzou avatar dependabot[bot] avatar fallion avatar gokhan-unal avatar hoangvvo avatar husseinmorsy avatar lfades avatar macrozone avatar moonsupport avatar oleg-rdk avatar oliviertassinari avatar qw-in avatar rajington avatar robertcoopercode avatar serranoarevalo avatar wesbos avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

next-with-apollo's Issues

React Hooks support

This issue is not to allow the usage of withApollo as a hook, because it needs to have access to getInitialProps, and it's a static method. This is to have a reminder that as soon as [email protected] gets out the dependency needs to be updated, otherwise getDataFromTree will break the new react hooks. Maybe I should create a beta version of this package too.

Related to react-apollo#2533 and react-apollo#2541

Initial SSR Fails on Deploy

We have a Next.js frontend with a custom express server and an Apollo Server graphql backend both deployed to heroku. Everything works perfectly with SSR when run locally, but when we move to the deployment something breaks and the cookies are not being passed in the headers during SSR. The cookies are httpOnly, they're available/working perfectly through client-side rendering. This is how we are setting up the apollo-client using next-with-apollo

export default withApollo(({ headers }) => {
	const ssrMode = !process.browser;

	const httpLink = createHttpLink({
		uri: GRAPHL_URI
	});

	const wsLink =
		!ssrMode &&
		new WebSocketLink({
			uri: process.env.NODE_ENV === "development" ? wsEndpoint : wsProdEndpoint,
			options: {
				reconnect: true
			}
		});

	const contextLink = setContext(() => ({
		fetchOptions: {
			credentials: "include"
		},
		headers
	}));

  let link = ApolloLink.from([ contextLink, httpLink]);

  if (!ssrMode) {
    link = split(
      // split based on operation type
      ({ query }) => {
        const definition = getMainDefinition(query);
        return definition.kind === "OperationDefinition" && definition.operation === "subscription";
      },
      wsLink,
      link
    );
  }

  const cache = new InMemoryCache({
    dataIdFromObject: ({ id, __typename }) => (id && __typename ? __typename + id : null)
  });

  return new ApolloClient({
    link,
    ssrMode,
    cache,
  });
});

And this is how we are trying to query our graphql backend during getInitialProps on our Index.js page

Index.getInitialProps = async ctx => {
	if (ctx.req && ctx.req.headers) {
		console.log(ctx.req.headers, "request headers");
	}
	const {data} = await ctx.apolloClient.query({
    query: CURRENT_USER_QUERY
  });
	console.log("init props", data);

	return {};
};

The console log inside getInitialProps shows that the headers are not in the request as they should be and the data always comes back as undefined (since the headers aren't being passed in).

We've tried just about every variation for initializing the apollo client and we've also tried changing what we can on our backend to make things works, but haven't made any headway. We generally get one of two errors during the initial getDataFromTree during SSR, the first being cannot POST and the second being Not Implemented. We're kinda at a loss for what we need to change to make this work, so we'd appreciate any and all suggestions.

Typescript Example?

Are there any typescript examples that use this library that you know of?

writeQuery in getInitialProps

I am using apollo-link-state and I'm trying to achieve a client store mutation:

static async getInitialProps ({ apolloClient }) {
  await apolloClient.mutate({
    mutation: MUTATION_WRITE_FACET
  })
  return {}
}

The mutation triggers my resolver successfully:

import { QUERY_GET_FACET } from "@graphql/Facet/query/GetFacet"

export const AddFacet = (_, variables, { cache, getCacheKey }) => {
  const results = cache.readQuery({ query: QUERY_GET_FACET })
  const facet = {
    ...results.facet,
    foo: "baz"
  }
  const data = { facet }
  cache.writeData({ data })
  return null
}

However, when I run a query in Apollo dev tools, I can see the cache hasn't changed. Am I doing something wrong here?

url prop not immediately available

Intro

With next.js 6, with a custom _app.js, you have to add the following code to have the url prop available to components (see vercel/next.js#4284):

import React from 'react';
import App, { Container } from 'next/app';

export default class MyApp extends App {

  static async getInitialProps({ Component, ctx }) {
    let pageProps = {};

    if (Component.getInitialProps) {
      pageProps = await Component.getInitialProps(ctx);
    }

    return { pageProps };
  }

  createUrl = (router) => {
    // This is to make sure we don't references the router object at call time
    const { pathname, asPath, query } = router;
    return {
      get query() {
        return query;
      },
      get pathname() {
        return pathname;
      },
      get asPath() {
        return asPath;
      },
      back: () => {
        router.back();
      },
      push: (url, as) => router.push(url, as),
      pushTo: (href, as) => {
        const pushRoute = as ? href : null;
        const pushUrl = as || href;

        return router.push(pushRoute, pushUrl);
      },
      replace: (url, as) => router.replace(url, as),
      replaceTo: (href, as) => {
        const replaceRoute = as ? href : null;
        const replaceUrl = as || href;

        return router.replace(replaceRoute, replaceUrl);
      },
    };
  }

  render() {
    const { Component, pageProps, router } = this.props;
    const url = this.createUrl(router);
    return (
      <Container>
        <Component {...pageProps} url={url} />
      </Container>);
  }

}

The problem

Now, the problem is that, using next-with-apollo this url property is not immediately available when you use it as a query parameter, in a "old-fashioned" HOC graphql()

graphql(getCategory, {
  options: ({ url }) => ({
    variables: { seoName: url.query.seoName }
  })
})

It is immediately available only if I modify the withApollo code to spread on the component also a url prop created in this way:

const url = {
  pathname: appCtx.router.pathname,
  query: appCtx.router.query
}

Otherwise I have to skip the query when url is not available to avoid GraphQL errors.

Is it an issue? If not, what would you suggest?

Thank you,
Matteo

GraphQL error occurred [getDataFromTree] TypeError: Cannot read property 'current' of undefined

I've got a very small withData.js script and using with [email protected], and I'm constantly seeing the following error both on the server side and the client side:

GraphQL error occurred [getDataFromTree] TypeError: Cannot read property 'current' of undefined
    at ReactDOMServerRenderer.read (app/node_modules/next-with-apollo/node_modules/react-dom/cjs/react-dom-server.node.development.js:3067:49)
    at renderToStaticMarkup (app/node_modules/next-with-apollo/node_modules/react-dom/cjs/react-dom-server.node.development.js:3604:27)
    at process (app/node_modules/next-with-apollo/node_modules/react-apollo/react-apollo.umd.js:118:24)

I've got a suspicion that it's not really the next-with-apollo that's causing it, but I honestly don't know where to start to debug it.

Any idea?

Preloading data not working on ssr nor client-side-routing

Hi i just tried this library and I'm running into the same issue described here #37.

It doesn't matter if I set 'always', 'never' or 'ssr' as the 'getDataFromTree' option. The result is always the same. The page is rendered before the data was loaded and the request to load the data happens on client side every time.

I created a small sample repo:
https://github.com/timojokinen/next-pokemon

The backend I used is this:
https://github.com/lucasbento/graphql-pokemon

I can't seem to find out what the problem is, I followed the instructions in the readme.

Type error with typescript using example

I'm following the example to set up next-with-apollo and am trying to do so using typescript instead of regular JavaScript. However, I'm getting the follow error when I do so:

[ts]
Argument of type 'typeof MyApp' is not assignable to parameter of type 'typeof App'.
  Types of parameters 'props' and 'props' are incompatible.
    Type 'TProps & AppComponentProps' is not assignable to type 'Props & AppComponentProps'.
      Type 'TProps & AppComponentProps' is not assignable to type 'Props'.
        Property 'apollo' is missing in type 'AppComponentProps'.
class MyApp

Here is my _app.tsx

import App, { Container } from 'next/app';
import ApolloClient from 'apollo-boost';
import { ApolloProvider } from 'react-apollo';
import withApollo from '../lib/withApollo';

interface Props {
  apollo: ApolloClient<any>;
}

class MyApp extends App<Props> {
  render() {
    const { Component, pageProps, apollo } = this.props;

    return (
      <Container>
        <ApolloProvider client={apollo}>
          <Component {...pageProps} />
        </ApolloProvider>
      </Container>
    );
  }
}

export default withApollo(MyApp);

The withApollo.ts didn't change from the example in the README.

Did I miss some simple here? I assumed given that this was written in TypeScript that it should work pretty simply.

Thanks!!

SSR fails when graphql query throw Error

Hello,
I have a problem with throwing errors by graphql (in my case with authorization).  I want to throw an Error when the user is not logged in. However, in this case, SSR doesn't work. "Loading ..." appears on the client's side, then the following message appears: "Network error: Can not read property 'req' of undefined".

It seems "getDataFromTree" parameter is always set to NEVER

I tried to do it WITHOUT getDataFromTree, with it set to always, ssr, never it seems that Apollo never tried to pull data (seems to defaulted to never).

Facebook / Google failed to get anything from SSR.

In my pages, I have something like

<Query query={GET_PAGE} variables={{ slug: 'terms', locale: this.props.query.locale }}>
        {({ loading, error, data, refetch, networkStatus }) => {
          console.log('querying graphql...');
          console.log('loading:', loading);
          console.log('networkStatus:', networkStatus);

and loading always returns true initially, even when it was the initial load from the server (SSR did not pull in data).

export default withApollo(
  () => new ApolloClient({ uri: GRAPHQL_URL }),
  {
    getDataFromTree: 'always'
  }
)

In the previous version of next-with-apollo v3.2.1, I don't think getDataFromTree was available, and console.log('loading:', loading); always was 'loaded'.

I have switched my code over to use https://github.com/zeit/next.js/blob/master/examples/with-apollo/pages/_app.js

and it seems to be working correctly now.

In my pages,

  1. loading is false as soon as the site is loaded from the server (SSR)
  2. subsequent load, loading started off as true as the app query the graphql server.

Use client.query on front-end part

Hi !

I would like to know if it's possible to use withApollo on front-end part, in componentDidMount for example. I don't like the react-apollo jsx. So I prefer to use client.query(). Do you know if it's possible ?

Use with local state management [Apollo client 2.5]

hi,
i setup project For friendly SEO correct the data. next-with-apollo great for me.

But Today i think about Local state management Because i want to use the couple state management . I don't idea to work it. the guideline document in apollographql website not implement in Nextjs i can't Set local state in my project.

please suggestion for me to use a couple modules.
thank you

Typescript

Apollo packages are built with Typescript, this should not be an exception

forward "set-cookie" when SSR occurs

forwarding cookies from Next to Apollo works as expected
But the other way around doesn't work for me.

When my Apollo server is returning a "set-cookie" header it is not returned from Next

Is there a way to forward the "set-cookie" header when SSR occurs?

Conditional Rendering Forces Data Loading on Client Side

DEMO REPO: https://github.com/mattfwood/next-apollo-issue
LIVE EXAMPLE: https://advanced-react-frontend.herokuapp.com/orders

  • To recreate, create an account and try to go to a "restricted" page like /orders

I've been stuck on this issue for 8+ hours with absolutely no luck.

For context, I'm following this course and I've asked for help on that end as well, but I'm starting to think it might be a limitation / issue with either this package or NextJS itself.

I have this wrapper component that I'm using to check if certain views are authenticated.

Basically, it looks like if I'm using a wrapper component like this, it causes data to be forced to be fetched on the client side, causing the loading state "flash" that NextJS is typically designed to avoid.

I'm guessing that there's an issue between next-with-apollo fetching the data and NextJS knowing if it should be rendering the SignIn component or the children. It does eventually get hydrated when the page loads, but it still causes that "flash" of the incorrect state, which means that any view that's "protected" in this way would flash a login screen.

The only error that NextJS is emitting that is this:
[Network error]: SyntaxError: Unexpected token N in JSON at position 0

I know that this means that some request to my server is returning HTML instead of JSON, but when I check my server logs there isn't any request that's returning HTML. And I know my endpoints are correct because all the other data eventually gets loaded, but only after it's mounted. It looks like the request only fails on the server side (which is why it's only being shown in the NextJS logs).

Here's a list of additional observations after struggling with this for almost two full days:

  • It only happens if the page you initially load has the wrapper component. Meaning if you go to a non-protected page and then click to a restricted page, it doesn't "flash"
  • It doesn't seem to happen when running in development, only in production (doing next build and next start as opposed to next).

Could we enable operations on the apollo cache (during SSR) before extracting initialState?

Hi there,

Don't know if this is unusual requirement or not, but here is what I'd like to be able to do:

Using the next-with-apollo HOC works a treat with all my queries to an Apollo Server, but I also have client state that needs to be set in the Apollo Client cache based on the data that is collected in getDataFromTree. For example, I run a query to get a set of addresses from my graphql API but then I need to be able to set the default address as the selected one in the Apollo Client local state. If I wait until the client renders the update to make this updates (via mutations) then I see a flash of server rendered content with the data from my graphql API before seeing the client state take effect.

I initially thought I had the power to fix this and have my client / local state defaulted corrected as part of the SSR (as I can access the cache and the initialState in the clientFn that I configure the withApollo HOC with). But I found that this wasn't working (my components rendered as though all they had access to was the back-end data). Here is some semi-psuedo code showing what I was doing:

const initializeClientData = cache => {
    // Run some queries against the cache and (based
    // on that data) return data to write to the cache.
    // I want this to be added to the initialState.
    try {
        const getAddresses = { query: GET_ADDRESSES };
        const { addresses = [] } = cache.readQuery(getAddresses);
        return {
            selectedAddress: addresses.find(({ isDefault }) => !!isDefault) || null
        };
    } catch (e) {
        return {};
    }
}

export default withApollo(
    ({ initialState }) => {
        // Do ApolloClient link config things.

        const cache = new InMemoryCache().restore(initialState || {});
        const data = initializeClientData(cache);
        cache.writeData({ data });

        // Do more things.

        return new ApolloClient({
            cache,
            ...otherThings
        });
    }
)

When debugging this I found that my updates to the cache (which I make in the clientFn) were indeed happening... but were being overwritten. The getClient function (when it runs in the withApollo constructor) overwrites my updates to the cache with the initialState (which is calculated before my cache.writeData() changes are applied), erasing the additional data that I have written to it in my clientFn:

https://github.com/lfades/next-with-apollo/blob/master/src/withApollo.tsx#L104
https://github.com/lfades/next-with-apollo/blob/master/src/apollo.ts#L42

Proposed solution (please forgive the lack of TypeScript):

I want to be able to run updates on the cache when server-rendering (in the getInitialProps of the withApollo HOC) after doing the getDataFromTree but before the cache data is extracted and set as the apolloState.data (initialState). I need the ability to operate on the cache here:

https://github.com/lfades/next-with-apollo/blob/master/src/withApollo.tsx#L83

I've gotten this to work nicely by adding an optional function to the options (which I have tentatively called "initializeClientData") that is passed the cache (so it can perform whatever operations are needed) before the initialState is extracted from it. It works on my machine... gives me the ability to SSR my app with all of the client state correctly set based on the back-end data fetched in getDataFromTree.

if (options.getDataFromTree === 'always' || (options.getDataFromTree === 'ssr' && ssrMode)) {
    try {
        await getDataFromTree(
            <App
                {...appProps}
                Component={Component}
                router={router}
                apolloState={apolloState}
                apollo={apollo}
            />
        );
    } catch (error) {
        // Prevent Apollo Client GraphQL errors from crashing SSR.
        if (process.env.NODE_ENV !== 'production') {
            // tslint:disable-next-line no-console This is a necessary debugging log
            console.error('GraphQL error occurred [getDataFromTree]', error);
        }
    }

    if (typeof options.initializeClientData === 'function') {
        await options.initializeClientData(apollo.cache);
    }

    if (ssrMode) {
        // getDataFromTree does not call componentWillUnmount
        // head side effect therefore need to be cleared manually
        Head.rewind();
    }

    apolloState.data = apollo.cache.extract();
}

Any thoughts on this proposal? Would you be happy for me to PR this update?

No Persistant cache for local queries

Hi ! :)
I didn't find why I can't have Persistant cache with your library.
I tried to setup all by myself instead but have so many errors.

Do you have an idea ?
I saw on some issues that I need to setup persist cache before init Apollo.

Thanks !

How to make SSR work with multiple client ?

Both Apollo store hydrated before the first render, but the Test2 component will re-fetch after it mounted.

// apollo.ts
export const githubApolloClient = new ApolloClient({
  uri: 'https://api.github.com/graphql',
  headers: { authorization: `Bearer ${process.env.GITHUB_TOKEN}` },
});

export const anotherApolloClient = new ApolloClient({
  uri: 'https://api.graph.cool/simple/v1/cixmkt2ul01q00122mksg82pn',
});
// _app.tsx
export default withApollo(() => githubApolloClient)(MyApp);
// index.tsx
render(){
  return (
    <div>
        <Test1 />
        <Test2 />
    </div>
  )
}
// Test1.tsx
return (
  <Query query={query}>
    {({  data }) => {
      return <pre>{JSON.stringify(data, null, 2)}</pre>;
    }}
  </Query>
);
// Test2.tsx
// pass another apollo client as props to Query Component
return(
  <Query query={query} client={anotherApolloClient}>
      {({ data }) => {
        return <pre>{JSON.stringify(data, null, 2)}</pre>;
      }}
  </Query>
)

Typings for `client` object are incorrect

In the readme, it says you can do this:

withApollo({
  client: () => ({
    cache: new InMemoryCache()
  }),
  link: {
    http: new HttpLink({
      uri: GRAPHQL_URL
    })
  }
})

And this works correctly, except that TypeScript gives the error: Property 'link' is missing in type '{ cache: InMemoryCache; }'.

I haven't made a PR yet because I don't know if the docs should be updated, or the types should be updated (and if so, how, since they just use the ApolloClient types).

Thank you

Nice helper. Next was really missing something like this. :)

Question: why is initialState running on server side?

When I do a hard refresh, and add a console.log in my createClient function, I can see that the first call includes the headers but there's a second call that only has initialState - which means somewhere the apollo client is being returned with no headers attached - which, I'm guessing means it'll fail auth'ed requests?

I'm using [email protected].

CTX undefined

Trying to use your example with apollo-boost while setting an authorization header, but contect ctx always seems to be undefined?

How do I require context while still using your HOC?

// apollo.js
import withApollo from 'next-with-apollo';
import ApolloClient from 'apollo-boost';
import getConfig from 'next/config';
import { getCookieJwt } from './auth';

const { publicRuntimeConfig } = getConfig();

export default withApollo(
  ({ ctx, headers }) => {
    return new ApolloClient({
      uri: `${publicRuntimeConfig.SERVER_URL}/api`,
      request: async operation => {
        const token = await getCookieJwt(ctx); //ctx is undefined
        operation.setContext({
          headers: {
            authorization: token ? `Bearer ${token}` : ''
          }
        });
      }
    });
  },
);

Forward cookies from client

Thanks for the quick resolution of the last issue :)
I am currently using regular old cookies for my sessions and I'm wondering if there is a way to "forward" them on from my Next server to my backend graphql server?

My apollo boost is currently configured to send cookies as follows:

fetchOptions: {
    credentials: 'same-origin'
}

This means when the request comes from the frontend my graphql server gets the cookie as it is supposed to. When the request is sent from the backend, however, the cookie is in context.req.headers.cookie which doesn't seem to be sent to the graphql server.
Would the easiest way be to set the cookie header on the server side to context.req.headers.cookie for each server side request?

Thanks

Apollo cache seems to be undefined and that's causing an error.

I can't seem to get this package to work. I think all configurations are ok but I'm getting this error when starting the server.

TypeError: Cannot read property 'extract' of undefined at {PROJECT}/node_modules/next-with-apollo/lib/withApollo.js:135:61

Here's my current config. I'd really like some help.

_app.js

    // Import modules
    import App, { Container } from 'next/app';
    import { ApolloProvider } from 'react-apollo';

    // Import local modules
    import withApollo from '../lib/withApollo';

    // Define custom App
    class CustomApp extends App {

        render() {

            const { Component, pageProps, apollo } = this.props;

            return (
                <Container>
                    <ApolloProvider client={apollo}>
                        <Component {...pageProps} />
                    </ApolloProvider>
                </Container>
            );

        }

    }

    // Export custom App
    export default withApollo(CustomApp)

withApollo.js

    // Import modules
    import withApollo from 'next-with-apollo';
    import { InMemoryCache } from 'apollo-cache-inmemory';
    import { WebSocketLink } from 'apollo-link-ws';
    import { HttpLink } from 'apollo-link-http';


    const GRAPHQL_URL = 'http://localhost:3000/graphql';
    const WS_URL = 'http://localhost:3000/subscriptions';

    // Export wrapper

    export default withApollo({

        client: () => ({
            cache: new InMemoryCache()
        }),

        link: {
            http: new HttpLink({
                uri: GRAPHQL_URL
            })
        }

    })

rendering twice when change routes, and routing is passing previous url

Hello,

I notice adding in _app.js a console.log(this.props.routes) that is printing twice the router, but the main problem is that first print the previous url and then the current url. it happens using the Link for navigation only.

I have an example project.
https://github.com/xpromx/nextjs-apollo-example

with this problem when I enter to the page /song/:id the first time I'm receiving in the router a diff url with diff params so my query make this error:

GraphQL error occurred [getDataFromTree] Error: GraphQL error: Variable "$id" of required type "Int!" was not provided.

any ideas?

Support next.js 8+ (canary)

I would love to use next-with-apollo with the latest (canary) version of next.js. Would you be willing to merge by PR and maybe publish a canary-tagged version of this project too? Thanks!

#43

Desired behavior?

Hi, i was looking into some examples using something similar to this HOC, and i noticed that on every page change, is like all the App component is being unmounted and then mounted again (while in the normal Next.JS link navigation or other With-Apollo similar examples this doesn't happend). Is this normal?
Thanks!

page render() called twice after this HOC applied

Hi, once I applied this HOC, even the simplest page will be rendered twice during client navigation.
I tried the latest version 4.0.0 with next.js 9.0.2, and this issue also exists with previous version.
Anyone know how to fix this issue?

Thanks

Support apollo-link-state

Thanks for this library!

It would be great if support for apollo-link-state could be added.

There is currently this issue which produces a [Network error]: TypeError: Cannot read property 'propertyName' of undefined for properties with a @client directive.

As soon as that's resolved, it would be a nice addition to this helper library.

Use PeerDependency instead of depend on next

i just updated to [email protected] and doing yarn list gives me this

yarn list v1.9.4
warning Filtering by arguments is deprecated. Please use the pattern option instead.
├─ [email protected]
│  └─ [email protected]
└─ [email protected]
Done in 3.03s.

I think that this can be avoided (as well as some bundle sizing issues that I saw too) by making next a peer-dependency instead of a dependency

you could also add it to dev-dependencies if you want it to be available when doing dev

Along with all of the types

    "@types/graphql": "0.12.7",
    "@types/next": "^6.0.4",
    "@types/prop-types": "^15.5.2",
    "@types/react": "^16.3.14",

Passing context instead of header to clientFn

Hi,
the code I'm currently writing is in an awkward spot: I want to use Apollo's SchemaLink to avoid an extra HTTP request. However, I am also using TypeORM which is heavily decorator based. Apparently, NextJS is not transforming decorators if they are in client-side code but throws an error instead. Of course, I am using the IgnorePlugin for the client side build, but the build is still failing (this is due to the server build of /pages).
Now, my attempt to fix the problem is to create the schema link before calling the handle function, but I am not able to pass the Apollo client to clientFn, because that function only takes the headers as an argument. I'd propose to change https://github.com/lfades/next-with-apollo/blob/master/src/withApollo.tsx#L46 to use ctx instead of headers. I'd be happy to make a PR, just let me know what you think first :)

[with-sentry] Can't catch error in _app.jsx

Hi :)
I tried to integrate sentry in my nextjs project with the official with-sentry example in nextjs repo. But in production errors are not catch. I investigate a little bit and I found that withApollo catch all errors before rendering _app.jsx. And so I can't catch errors in my app.jsx getInitialProps. So I tried to catch the error inside the withApollo try/catch and it works !
But it's not a solution to catch error like this ! Do you have a solution to only catch error in _app.jsx ?
And by the way all errors in dev mod are logs as GraphQL errors because of that console.error('GraphQL error occurred [getDataFromTree]', error);

can't use setstate when use <Link> second page

the first page a will receive data from graphql. second time I clicked nextjs not render the new data from graphql (another link) but the same link same data in previous creche render correctly. please see the capture screen
https://media.giphy.com/media/eMUztsvqbousK4yyQV/giphy.gif

ps. I receive data from {data} render will completed but second page graphql not load = can't set state onCompleted={}
<Query query={QUER_DATA_EDIT} variables={{ id }} onCompleted={(data) => this.setData(data.edit_categories[0].data[0])}> {({ data, loading, error }) => { if (loading) return <Loader_Component /> if (data) return Render_edit(data) }} </Query>

Can't find field X on object undefined

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?

How to handle multi

I have a backend GraphQL server but also want to connect with a 3rd party GraphQL API. How should we handle multiple Apollo clients? Should we wrap the HOC twice?

Tests

I'll be focused in doing tests with ts-jest after the package has been rewrited with Typescript

Version 3 breaking changes

Some changes have been made in the branch v2.2 that got me thinking, do we really need to have custom configs to create an ApolloClient ? it would be much simpler to just have support for any ApolloClient, specially because I think most people will go for apollo-boost, the only downside I see is to implement subscriptions and other stuff that's not yet in apollo-boost (related to this issue) but even for that we can just create our custom ApolloClient and follow Apollo's docs to integrate the different links

Related to #12

Do we need to pass initialState to ApolloClient?

export default withApollo(({ ctx, initialState }) => {
  return new ApolloClient({
    uri: process.env.GQL_ENDPOINT,
    // Do I need this line? or it will handle automatically
    clientState: initialState,
  });
})(MyApp);

Cookies not being sent.

I can't seem to get cookies to work with this HOC, I need to send the cookies to the server (on the same domain) both in SSR and CSR for authentication porpuses but is just not working. Have you implemented any authentication flow with this HOC? Am I missing something? I created both a client with Apollo boost and manually as well but still is not working.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.