question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Accessing ctx, headers from inside withApollo export causes ctx to be undefined inside of WithApollo.getInitialProps.

See original GitHub issue

I’m trying to access a token from a cookie and set it to the headers for authorization. When trying to access ctx and headers properties through the withApollo export, I get the following error:

_app.js:7 Uncaught TypeError: Cannot read property 'req' of undefined
    at nextCookies (index.js:8)
    at push../lib/withApollo.js.__webpack_exports__.default.next_with_apollo__WEBPACK_IMPORTED_MODULE_9___default.render (withApollo.js:7)
    at getClient (apollo.js:23)
    at Object.initApollo [as default] (apollo.js:14)
    at WithApollo(Profile) (withApollo.js:23)
    at renderWithHooks (react-dom.development.js:16260)
    at mountIndeterminateComponent (react-dom.development.js:18794)
    at beginWork$1 (react-dom.development.js:20162)
    at HTMLUnknownElement.callCallback (react-dom.development.js:336)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:385)
    at invokeGuardedCallback (react-dom.development.js:440)
    at beginWork$$1 (react-dom.development.js:25780)
    at performUnitOfWork (react-dom.development.js:24695)
    at workLoopSync (react-dom.development.js:24671)
    at performSyncWorkOnRoot (react-dom.development.js:24270)
    at scheduleUpdateOnFiber (react-dom.development.js:23698)
    at updateContainer (react-dom.development.js:27103)
    at react-dom.development.js:27528
    at unbatchedUpdates (react-dom.development.js:24433)
    at legacyRenderSubtreeIntoContainer (react-dom.development.js:27527)
    at Object.hydrate (react-dom.development.js:27591)
    at renderReactElement (index.js:31)
    at doRender$ (index.js:38)
    at tryCatch (runtime.js:45)
    at Generator.invoke [as _invoke] (runtime.js:271)
    at Generator.prototype.<computed> [as next] (runtime.js:97)
    at tryCatch (runtime.js:45)
    at invoke (runtime.js:135)
    at runtime.js:170
    at new Promise (<anonymous>)
    at callInvokeWithMethodAndArg (runtime.js:169)
    at AsyncIterator.enqueue [as _invoke] (runtime.js:192)
    at AsyncIterator.prototype.<computed> [as next] (runtime.js:97)
    at Object.push../node_modules/regenerator-runtime/runtime.js.exports.async (runtime.js:216)
    at doRender (index.js:34)
    at render$ (index.js:18)
    at tryCatch (runtime.js:45)
    at Generator.invoke [as _invoke] (runtime.js:271)
    at Generator.prototype.<computed> [as next] (runtime.js:97)
    at tryCatch (runtime.js:45)
    at invoke (runtime.js:135)
    at runtime.js:170
    at new Promise (<anonymous>)
    at callInvokeWithMethodAndArg (runtime.js:169)
    at AsyncIterator.enqueue [as _invoke] (runtime.js:192)
    at AsyncIterator.prototype.<computed> [as next] (runtime.js:97)
    at Object.push../node_modules/regenerator-runtime/runtime.js.exports.async (runtime.js:216)
    at render (index.js:18)
    at next-dev.js:4
    at fouc.js:4

From what I can tell it seems like it’s erroring on ctx.req in the WithApollo.getInitialProps from /next-with-apollo/lib/withApollo

 WithApollo.displayName = `WithApollo(${getDisplayName(Page)})`;
        if (getInitialProps || getDataFromTree) {
            WithApollo.getInitialProps = async (pageCtx) => {
                const ctx = 'Component' in pageCtx ? pageCtx.ctx : pageCtx;
                const { AppTree } = pageCtx;
                const headers = ctx.req ? ctx.req.headers : {};
                const apollo = apollo_1.default(client, { ctx, headers });
                const apolloState = {};
                let pageProps = {};
                if (getInitialProps) {...

Here’s where I’m trying to access the token and set the headers

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

export default withApollo(
  ({ initialState, ctx, headers }) => {
    const { token } = Cookie(ctx)
    return new ApolloClient({
      uri: 'https://graphql.api.com',
      cache: new InMemoryCache().restore(initialState || {}),
      headers: {
        ...headers,
        authorization: token ? `Bearer ${token}` : ''
      }
    });
  },
  {
    render: ({ Page, props }) => {
      return (
        <ApolloProvider client={props.apollo}>
          <Page {...props} />
        </ApolloProvider>
      );
    }
  }
);

Here’s some example components trying to use them

import { useQuery } from '@apollo/react-hooks'

const ProfileCard = ({ id }) => {

  const GET_USER = gql`
    {
      user (id: $id) {
        id
        name
        email
      }
    }
  `
  const { loading, error, data } = useQuery(GET_USER, {  variables: { id })

  if (loading) return <div>loading ...</div>
  if (error) return <div>Error</div>

  const { name, email } = data

  return (
    <ul>
      <li>
        Id: {name} */}
      </li>
      <li>
        Name: {email} */}
      </li>
    </ul>
  )
}

export default ProfileCard
import Layout from '../../components/Layout'
import ProfileCard from '../../components/ProfileCard'
import withApollo from '../../lib/withApollo'
import { getDataFromTree } from '@apollo/react-ssr'

function Profile({ id }) {

  return (
    <Layout>
      <ProfileCard id={id} />
    </Layout>
  )

}

export default withApollo(Profile, { getDataFromTree })

I’m fairly certain it’s something I’m doing wrong, but I can’t spot it. I’ve tried with and without getDataFromTree (even though initalState, ctx, and headers are undefined client side). If I remove the ctx and header properties from the destructuring, and hard code the token, it functions. After going over the apollo docs, this is what seemed to be the correct method. How should I be trying to access these?

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
DoubleBridgescommented, Feb 28, 2020

Thank you for all the help. I got it to work with:

import withApollo from "next-with-apollo";
import ApolloClient, { InMemoryCache } from "apollo-boost";
import { ApolloProvider } from "@apollo/react-hooks";
import Cookie from "js-cookie";

export default withApollo(
  ({ initialState, headers }) => {
    let token = Cookie.get("token");
    return new ApolloClient({
      uri: `https://graphql.api.com`,
      cache: new InMemoryCache().restore(initialState || {}),
      headers: {
        ...headers,
        authorization: token ? `Bearer ${token}` : ""
      }
    });
  },
  {
    render: ({ Page, props }) => {
      return (
        <ApolloProvider client={props.apollo}>
          <Page {...props} />
        </ApolloProvider>
      );
    }
  }
);

Where I’m assuming js-cookie is reading the document.cookie. This is my first non-trivial Next app and the first time I’ve used Apollo at all, so it’s been a big learning curve.

0reactions
lfadescommented, Feb 17, 2020

@DoubleBridges ctx and headers are only for the server, once you’re in the browser (after the first render with SSR) you don’t need to access those objects, the cookie will be sent by the browser if you use credentials: 'same-origin' or credentials: 'include'.

If you need to send the cookie inside the authorization header use document.cookie once you’re in the browser instead of ctx.

If your cookie is httpOnly (not available in document.cookie) then don’t use the authorization header.

Read more comments on GitHub >

github_iconTop Results From Across the Web

next-with-apollo, SSR does not work, request is done on client
Here is the solution I am using. It allows to wrap the page(main component) in the HOC and then make request ssr or...
Read more >
Apollo Graphql integration for Next.js - Morioh
headers - This is ctx.req.headers , in the client it will be undefined; router - This is the router object sent by getInitialProps...
Read more >
express-graphql : context is always undefined - You.com
There's two common reasons your field or fields are resolving to null: 1) returning data in the wrong shape inside your resolver; and...
Read more >
Setting up Apollo GraphQL in Next.js with Server Side ...
Useful if you want to use apolloClient * inside getStaticProps, ... Boolean(ctx.ctx); // We consider installing `withApollo({ ssr: true })` ...
Read more >
Up and running with Next.js and Hasura in no time - USEO
In this blog-post, the only action we will do API-wise is reading the data with a GraphQL query - no mutations or subscriptions...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found