代码之家  ›  专栏  ›  技术社区  ›  Omar Dulaimi

getStaticProps在prod和dev处返回空对象(下一个v9.5.1)

  •  0
  • Omar Dulaimi  · 技术社区  · 4 年前

    我遇到了一个奇怪的问题。使用最新的nextjs@9.5.1 这是有问题的代码:

    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;
    

    你知道为什么会发生这种情况吗?

    我尝试更改此文件中函数的顺序,并将道具串化,将返回的数据作为一个整体记录下来,但没有破坏,但运气不佳。

    如果这可能与此问题有关,我会使用自定义服务器和NextSeo库。

    更新:

    我进入了nextjs中的next-server.js文件,并记录了一些相关值:

    }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
    

    更新2: 问题似乎出现在custom_app中:

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

    Component.getInitialProps未定义,因此pageProps返回一个空对象。

    这是否意味着getStaticProps实际上并没有将props传递给自定义应用程序中的getInitialProps?

    更新3: appProps和pageProps均为空:

     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);
    

    更新4: 如果有人想看到自定义app,这是它,因为它可能是问题所在:

    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));
    

    更新5: 你可以在这里找到一个副本: https://github.com/omar-dulaimi/nextjs-no-staticprops-repro

    0 回复  |  直到 4 年前
        1
  •  1
  •   Omar Dulaimi    4 年前

    所以基本上这个问题与下一个redux包装包有关。它是在Nextjs的最新功能之后更新的,因此当我将项目更新到v9.5.1时,getStaticProps不起作用,因为我从未升级过下一个redux包装器版本或配置。

    希望这能在未来节省一些人的时间。正如Nextjs贡献者所建议的,这里的例子解释了这一切 https://github.com/vercel/next.js/tree/canary/examples/with-redux-wrapper