1
votes

I'm running into a weird issue. using the latest nextjs @9.5.1 Here's the code in question:

import Header from './header';
import Head from './head';
import Footer from './footer';
import { useEffect } from 'react';
import Utils from '../util/utils';
import { hostName } from '../config/variables';

function Privacy({ pageTitle, metaTitle, description, metaDescription, url }) {
    console.log("Privacy -> pageTitle", pageTitle)
    useEffect(() => {
        Utils.handleFBPixelPageView('Privacy');
    }, []);

    return (
        <div>
            <Head
                isAmpPage={false}
                pageTitle={pageTitle}
                description={description}
                url={url}
                metaTitle={metaTitle}
                metaDescription={metaDescription}
            />
            <Header isAmp={false} />
            <div className="privacy-main-panel">

            Hello there!
            </div>

            <style jsx global>{`
                .privacy-main-panel {
                    width: 1000px;
                    display: flex;
                    flex-direction: column;
                    text-align: right;
                    font-family: inherit;
                    padding-top: 20px;
                    margin: 0 auto;
                }
                h1 {
                    padding: 0;
                    margin: 5px 0;
                    line-height: 1;
                    margin-bottom: 25px;
                }
                h2,
                h3 {
                    padding: 0;
                    margin: 5px 0;
                    line-height: 1;
                }
                p {
                    margin-bottom: 10px;
                }
                ul {
                    margin: 0;
                    margin-bottom: 20px;
                }
                @media only screen and (max-width: 1000px) {
                    .privacy-main-panel {
                        width: 100vw;
                        padding: 20px;
                    }
                }
            `}</style>
            <Footer isVisibleOnMobile={true} />
        </div>
    );
}

export async function getStaticProps() {
    return {
        props: {
            pageTitle: 'text1',
            metaTitle: 'text2',
            description: 'text3',
            metaDescription: 'text4',
            url: `${hostName}/privacy`,
        },
    };
}

export default Privacy;

Any ideas why this might happen?

I tried changing the order of functions in this file, and also stringifying the props, logging the returned data as a whole without destructuring but with no luck.

I use a custom server and NextSeo library if that might have anything to do with this issue.

UPDATE:

I went inside next-server.js file inside nextjs and logged a few values related :

}renderToHTML -> pathname /privacy
result {
  components: {
    App: [Function: WrappedApp] {
      displayName: 'withRedux(f)',
      getInitialProps: [Function]
    },
    Document: [class MyDocument extends Document],
    Component: [Function: Privacy],
    buildManifest: {
      polyfillFiles: [Array],
      devFiles: [Array],
      ampDevFiles: [Array],
      lowPriorityFiles: [Array],
      pages: [Object],
      ampFirstPages: []
    },
    reactLoadableManifest: { './dev/noop': [Array] },
    pageConfig: {},
    getServerSideProps: undefined,
    getStaticProps: [AsyncFunction: getStaticProps],
    getStaticPaths: undefined
  },
  query: { _nextDataReq: undefined, amp: undefined }
}
this.renderOpts {
  poweredByHeader: true,
  canonicalBase: '',
  buildId: 'development',
  generateEtags: true,
  previewProps: {
    previewModeId: 'key',
    previewModeSigningKey: 'key',
    previewModeEncryptionKey: 'key'
  },
  customServer: true,
  ampOptimizerConfig: undefined,
  basePath: '',
  optimizeFonts: false,
  fontManifest: null,
  assetPrefix: '',
  dev: true,
  ErrorDebug: [Function: ReactDevOverlay],
  ampSkipValidation: false,
  ampValidator: [Function]
}

      components.getStaticProps:  Promise {
      {
        props: {
          pageTitle: 'text1',
          metaTitle: 'text2',
          description: 'text3',
          metaDescription: 'text4',
          url: 'http://localhost:3000/privacy'
        }
      }
    }
        query:  [Object: null prototype] {}
        params:  null
        all:  { _nextDataReq: undefined, amp: undefined }
        Privacy -> pageTitle undefined

UPDATE 2: The problem seems to be here in the custom _app:

  static async getInitialProps({ Component, ctx }) {
    const pageProps = Component.getInitialProps
        ? await Component.getInitialProps(ctx)
        : {};
    return { pageProps };
}

Component.getInitialProps is undefined so pageProps returns an empty object.

Does this mean that getStaticProps doesn't actually pass props to getInitialProps in the custom app?

UPDATE 3: Both appProps and pageProps are empty:

 const pageProps = AppContext.Component.getInitialProps ? 
     await AppContext.Component.getInitialProps(AppContext.ctx)
     : {};

 console.log('MyApp -> getInitialProps -> pageProps', pageProps);

 const appProps = App.getInitialProps ? await App.getInitialProps(AppContext): {};
 console.log('MyApp -> getInitialProps -> appProps', appProps);

UPDATE 4: here's the custom _app if anybody wants to see it since it could be the problem:

import withRedux from 'next-redux-wrapper';
import App from 'next/app';
import React from 'react';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import Amplify from 'aws-amplify';
import ReactPixel from 'react-facebook-pixel';
import Router from 'next/router';
import withGA from 'next-ga';
import * as Sentry from '@sentry/browser';
import MobileBarController from '../components/mobile-bar-controller';
import rootReducer from '../store/reducers/root-reducer';
import { userLogin } from '../store/actions/actions';
import Utils from '../util/utils';
import {
    apiUrl,
    facebookPixelId,
    sentryDsnFrontend,
} from '../config/variables';


const makeStore = (initialState, options) => {
    return createStore(rootReducer, initialState);
};

Amplify.configure({
    Auth: {
        identityPoolId: 'id',
        region: 'region',
    },
    API: {
        graphql_endpoint: apiUrl,
        region: 'region',
        identityPoolId: 'poolId',
    },
    bucket: 'items-bucket',
});

Sentry.init({
    dsn: `${sentryDsnFrontend}`,
});
class MyApp extends App {
    constructor(props) {
        super(props);
        if (!Utils.isServer()) {
            let user = Utils.getCookieAsJson('persist:user');
            let token = Utils.getCookie('user_token');
            if (user && token) {
                props.store.dispatch(userLogin(user, token));
            }
        }
    }
    static async getInitialProps({ Component, ctx }) {
        if (
            Utils.isServer() &&
            ctx &&
            ctx.req &&
            ctx.req.headers &&
            ctx.req.headers.cookie
        ) {
            let cookie = ctx.req.headers.cookie;
            if (cookie) {
                let cookies = cookie.split(';');
                let user = null;
                let token = null;

                for (let i = 0; i < cookies.length; i++) {
                    if (cookies[i].indexOf('persist:user') > -1) {
                        user = JSON.parse(
                            unescape(cookies[i].replace('persist:user=', ''))
                        );
                    } else if (cookies[i].indexOf('user_token') > -1) {
                        token = cookies[i].replace('user_token=', '');
                    }
                }
                if (user && token) {
                    ctx.store.dispatch(userLogin(user, token));
                }
            }
        }
        const pageProps = Component.getInitialProps
            ? await Component.getInitialProps(ctx)
            : {};
        return { pageProps };
    }

    componentDidMount() {
        ReactPixel.init(
            facebookPixelId,
            {},
            { debug: false, autoConfig: false }
        );
    }

    componentDidCatch(error, errorInfo) {
        Sentry.withScope((scope) => {
            Object.keys(errorInfo).forEach((key) => {
                scope.setExtra(key, errorInfo[key]);
            });

            Sentry.captureException(error);
        });

        super.componentDidCatch(error, errorInfo);
    }

    render() {
        const { Component, pageProps, store } = this.props;
        return (
            <Provider store={store}>
                <Component {...pageProps} />
                <MobileBarController />
            </Provider>
        );
    }
}

export default withRedux(makeStore)(withGA('GA-ID', Router)(MyApp));

UPDATE 5: You can find a repro here: https://github.com/omar-dulaimi/nextjs-no-staticprops-repro

1

1 Answers

1
votes

So basically the issue was related to next-redux-wrapper package. It was updated after the lastest Nextjs features and so when I updated my project to v9.5.1, getStaticProps didn't work because I never upgraded the next-redux-wrapper version nor config.

Hope this saves somebody's time in the future. As suggested by Nextjs contributor, this example here explains it all https://github.com/vercel/next.js/tree/canary/examples/with-redux-wrapper