FormidableLabs / next-urql

Convenience utilities for using urql with NextJS.
MIT License
56 stars 7 forks source link

pages getInitialProps no longer gets called #35

Closed addstar34 closed 4 years ago

addstar34 commented 4 years ago

I'm using withUrqlClient on my _app.js and when I add a getInitialProps to a page it's not getting triggered.

I'm wanting to add a HOC to certain pages that will check if the user is authenticated and if not redirect to the login page.

This is what code looks like when just trying to console log in a pages getInitialProps function.

// pages/_app.js

function MyApp({ Component, pageProps, accessToken }) {
  if (!isServer() && accessToken) {
    setToken(accessToken)
  }

  return <Component {...pageProps} />
}

MyApp.getInitialProps = async ctx => {
  if (isServer()) {
    const cookie = getCookie(ctx)
    if (cookie) {
      const accessToken = await getRefreshToken(cookie, ctx)
      return { accessToken }
    }
  }

  return {}
}

export default withUrqlClient(
  {
    url: process.env.GRAPHQL_ENDPOINT,
  },
  ssrEx => {
    return [
      dedupExchange,
      cacheExchange(),
      refreshTokenExchange(),
      ssrEx,
      fetchExchange,
    ]
  }
)(MyApp)
// pages/account.js

function Account() {
  return (
    <div>
      <h1>Account</h1>
    </div>
  )
}

Account.getInitialProps = async ctx => {
  // This never gets run
  console.log('Account.getInitialProps')
}

export default Account
addstar34 commented 4 years ago

ok silly me, you have to manually call the pages getInitialProps from within _app.js's getInitialProps as per the nextjs docs.

Eg:

import React from 'react'
import App from 'next/app'

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

// Only uncomment this method if you have blocking data requirements for
// every single page in your application. This disables the ability to
// perform automatic static optimization, causing every page in your app to
// be server-side rendered.
//
MyApp.getInitialProps = async (appContext) => {
  // calls page's `getInitialProps` and fills `appProps.pageProps`
  const appProps = await App.getInitialProps(appContext);

  return { ...appProps }
}

export default MyApp
jgoux commented 4 years ago

Hi @addstar34 , could you point me to the right doc? I'm in the same case, my urql queries aren't SSR anymore, and my code didn't change, maybe it's a real bug? I never had to define the getInitialProps myself, I just called withUrql on my App.

parkerziegler commented 4 years ago

@jgoux this has to do with some of the API discrepancies in Next between standard Page components and _app.js, both of which we're trying to support with this HoC. In order to use _app.js, we have to manually tell _app.js to call each wrapped component's getInitialProps function. @addstar34 linked the docs from here: https://nextjs.org/docs/advanced-features/custom-app and it is true that you'll need to implement _app's getInitialProps doing something like the following:

import NextApp from 'next/app';

const App = ({ Component, pageProps }) => {
   return <Component {...pageProps} />;
};

// Here's the additional work.
App.getInitialProps = async (ctx) => {
   // Under the hood, this calls each wrapped Page's `getInitialProps`.
   const appProps = await NextApp.getInitialProps(ctx);

   // appProps = { pageProps: { // Whatever is passed to the particular page being rendered. } }
   return {
      ...appProps
   };
};

I'll update our example to better demonstrate this!

parkerziegler commented 4 years ago

Part of the reason this wasn't behaving like this before is that we were essentially treating _app.js and Page components in the exact same manner, which introduces other bugs for the prepass step and can lead to incorrect results. The modifications made for v0.3.0 better align with Next's API, which I find a bit difficult to work with as well.

A good thing to note as well – this should only be an issue if you were trying to return some data from getInitialProps on one of your Page components. The SSR'ed queries should work exactly the same between these versions. If you're able to point me to a reproduction of your issue I'm happy to look more!