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

getInitialProps is not called unless _app.js extends next/app #615

Closed
justincy opened this issue Jan 14, 2020 · 19 comments
Closed

getInitialProps is not called unless _app.js extends next/app #615

justincy opened this issue Jan 14, 2020 · 19 comments

Comments

@justincy
Copy link

Describe the bug

getInitialProps is not called unless _app.js extends App from next/app. This prevents namespace splitting from working. This is a bug with next-i18next because next doesn't require App to be extended; next will call getInitialProps even when using a function component for _app.js. There examples use a function: https://nextjs.org/docs/advanced-features/custom-app

Occurs in next-i18next version

v4.0.0

Steps to reproduce

export a function component from _app.js instead of a class component that extends next/app.

Expected behaviour

I recognize that the docs for next-i18next use a class component, but it's not obvious that doing so is required, and perhaps it shouldn't be required since next doesn't require it.

@isaachinman
Copy link
Contributor

Fair point. Not exactly sure how hoist-non-react-statics would work for non-class components. Hoping to learn something new here. PRs very welcome!

@isaachinman
Copy link
Contributor

So, I looked into this a bit. While there may indeed be issues ahead with hoisting, the main problem here is with the existence of getInitialProps on the _app component.

The example in this repo works, because extending next/app will add in a getIntialProps that then calls the actual page-level getInitialProps.

In fact, if you follow the second example in the exact NextJs docs that you linked to, you'll find that everything works as expected:

import React from 'react'
import App from 'next/app'
import { appWithTranslation } from '../i18n'

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

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

export default appWithTranslation(MyApp)

@justincy
Copy link
Author

Thanks for figuring that out.

@chiqui3d
Copy link

chiqui3d commented Feb 10, 2020

please could you update the example repository
thanks

@isaachinman
Copy link
Contributor

@chiqui3d Update it in what way?

@chiqui3d
Copy link

The example didn't work for me, until I edited the _app.js file thanks to this issue, I almost went crazy.

https://github.com/isaachinman/next-i18next/blob/master/examples/simple/pages/_app.js

@isaachinman
Copy link
Contributor

@chiqui3d The example is deployed and runs at next-i18next.com. It is also covered by multiple end-to-end tests. Can you be more specific?

@chiqui3d
Copy link

chiqui3d commented Feb 10, 2020

So to apply Next with i18next, I have based on your example, and I did not work in any component pass props with the method getInitialProps, until I edited the file _app.js and I have added what you have commented here, as you can see in your example the file _app.js that does not include it.

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

@Huibean
Copy link

Huibean commented Feb 11, 2020

This works for me after use withTranslation

    const { Component, pageProps } = this.props;
    if (Component.WrappedComponent) {
      Component.getInitialProps = Component.WrappedComponent.getInitialProps
    }

@orifmilod
Copy link

@isaachinman Is there a way to inject it in a lower-level component but not _app, because when wrapping _app with appWithTranslation it opted-out of Automatic Static Optimization. (Mind that I have tried to use it in a Main component which its a wrapper for navbar and pages, but did not work, it gives me the error http://localhost:5000/src/server/locales/ru/common.json 404 (Not Found))

@7iomka
Copy link

7iomka commented May 6, 2020

@orifmilod same question to community!
How next.js docs (https://nextjs.org/docs/advanced-features/custom-app)
say:

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 }
// }

Any ideas?
Please!

@norbiu
Copy link

norbiu commented May 29, 2020

Modifying _app.js solved the issue I was having with trying to integrate next-i18next with next-with-apollo. Lucky I found this thread!

import App from 'next/app';

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

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

export default withApollo(appWithTranslation(MyApp));

Works the same way with withTranslation inside a certain page:

export default withApollo(withTranslation()(Collections));

@bymoe
Copy link

bymoe commented Jul 10, 2020

@norbiu Be aware that this might results in Error: Circular structure in "getInitialProps".

@nataliaroque77
Copy link

nataliaroque77 commented Oct 1, 2020

It resolve issue, translations work - but build will have warnings related to getInitialProps in appWithTranslation HOC
#840

@imCorfitz
Copy link

Not entirely sure, what I am facing here:

Screenshot 2020-12-01 at 10 12 45

@imCorfitz
Copy link

imCorfitz commented Dec 2, 2020

Not entirely sure, what I am facing here:

Screenshot 2020-12-01 at 10 12 45

Alrighty.. I know what I did wrong here. Kept getting these errors, but again, as mentioned countless times over and over "Read the Docs carefully".

First mistake in my case, looking at the 404.tsx file. I am importing withTranslation from next-i18next. This was done automatically by VSCode, so didn't think more of it, but in reality, this should be fetched from your custom i18n.ts file. So it should actually read import { withTranslation } from '@/lib/i18n';.

Now - I would then realise I would face another issue, but that is solely due to Next.js. https://github.com/vercel/next.js/blob/master/errors/404-get-initial-props.md

Next.js does not permit getInitialProps for the custom 404.tsx file as this should serve 100% as a static file for fast delivery. Since I am not able to pass initial props to 404, then I would again get the missing namespacesRequired array warning in the console. I reckon we could either detect the filename and not display the warning as a condition thereof, or we should link to a solution on how to use the _error.tsx instead of having a static 404 file.

@macshion
Copy link

So, I looked into this a bit. While there may indeed be issues ahead with hoisting, the main problem here is with the existence of getInitialProps on the _app component.

The example in this repo works, because extending next/app will add in a getIntialProps that then calls the actual page-level getInitialProps.

In fact, if you follow the second example in the exact NextJs docs that you linked to, you'll find that everything works as expected:

import React from 'react'
import App from 'next/app'
import { appWithTranslation } from '../i18n'

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

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

export default appWithTranslation(MyApp)

Thank you! It works for me. My code:

type Props = {
  topMenu: TopNavigatorType[]
} & AppProps
function MyApp({ Component, pageProps, topMenu }: Props): JSX.Element {
  return (
    <>
      <AppProvider value={{ menu: topMenu }}>
        <Component {...pageProps} />
      </AppProvider>
      <script src="/lib/baidu.qiao.js" async defer />
    </>
  )
}

type Init = {
  topMenu: TopNavigatorType[]
} & AppInitialProps

MyApp.getInitialProps = async (appContext: AppContextType<Router>) => {
  const topMenu = await request.get(NAVIGATION)
  const appProps = await App.getInitialProps(appContext)
  const props: Init = { topMenu: topMenu.data, ...appProps }
  return { ...props }
}

export default MyApp

@hydRAnger
Copy link

excuse me, has anyone seen this Property 'getInitialProps' does not exist on type 'FC<AppProps<{}>>',
when try this: MyApp.getInitialProps = async (appContext) => {...}

@yattias
Copy link

yattias commented Sep 9, 2021

For those of you who have an app with pages containing getStaticProps and others containing getInitialProps You will need to do something like this:

MyApp.getInitialProps = async (appContext) => {

  // Your static props paths
  const staticPropsPaths = [
    "/paper/[paperId]/[paperName]",
    "/hubs"
  ]

  if (process.browser || !staticPropsPaths.includes(appContext.router.route)) {
    const appProps = await App.getInitialProps(appContext)
    return { ...appProps }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests