在npm运行构建的预渲染页面上获取TypeError [英] Getting TypeError on prerendering page in npm run build

查看:44
本文介绍了在npm运行构建的预渲染页面上获取TypeError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Next.js应用程序中呈现此页面:

I am prerendering this page on my Next.js application:

const router = useRouter();

if (!router.isFallback && !postData?.slug) {
    return <p>hmm... looks like an error</p>
}

const formatDate = date => {
    const newDate = new Date(date);

    return `${newDate.getDate()}/${
        newDate.getMonth() + 1
    }/${newDate.getFullYear()}`
};


    return (
    <div className={styles.container}>
        <Head>
            <title>{postData.title}</title>
            <link rel='icon' href='/favicon.ico' />
        </Head>

        <main className={styles.main}>
            {router.isFallback ? (
                <h2>Loading...</h2>
            ) : (
                <article className={blogStyles.article}>
                    <div className={blogStyles.postmeta}>
                        <h1 className={styles.title}>{postData.title}</h1>
                        <p>{formatDate(postData.date)}</p>
                        <img src={postData.featuredImage.node.sourceUrl} />
                    </div>
                    <div
                        className='post-content content'
                        dangerouslySetInnerHTML={{ __html: postData.content }}
                    />
                </article>
            )}
            <p>
                <Link href={`/blog`}>
                    <a>Back</a>
                </Link>
            </p>
        </main>
    </div>
)

使用 getStaticProps()

    export async function getStaticProps({ params }) {
    const data = await getPost(params.slug);

    return {
      props: {
        postData: data.post
      }
    };
  }

使用 getStaticPaths()

export async function getStaticPaths() {
    const allPosts = await getAllPostsWithSlug();

    if (
        allPosts &&
        allPosts.edges !== null &&
        allPosts.edges.node !== null &&
        allPosts.edges.length > 0
    ) {
        return {
            paths: allPosts.edges.map(({ node }) => `/blog/${node.slug}`) || [],
            fallback: true
        }
    }

}

当我在本地运行它时,它可以正常工作,但是当我尝试使用 npm run build 对其进行部署时,它只给出 title 属性的错误:

When I run it locally it works fine but when I try to deploy it with npm run build it gives an error just for the title property only:

Error occurred prerendering page "/blog/[slug]". Read more: https://err.sh/next.js/prerender-error
TypeError: Cannot read property 'title' of undefined

这是令我困惑的部分,因为我不明白为什么错误仅出现在查询的1个属性(postData.title)上,而其他所有内容都正常运行.

This is the part that confuses me as I don't understand why the error is only on 1 property (postData.title) of the query and everything else loads fine.

我正在使用GraphQL创建查询:

I am using GraphQL to create the query:

export async function getPost(slug) {
    const data = await fetchAPI(
      `
      fragment PostFields on Post {
        title
        excerpt
        slug
        date
        featuredImage {
          node {
            sourceUrl
          }
        }
      }
      query PostBySlug($id: ID!, $idType: PostIdType!) {
        post(id: $id, idType: $idType) {
          ...PostFields
          content
        }
      }
    `,
      {
        variables: {
          id: slug,
          idType: 'SLUG'
        }
      }
    );

    return data;
}

我通过api.js文件导入此函数,并使用getStaticProps()函数中的数据.

I import this function through an api.js file and use the data in the getStaticProps() function.

任何对此的帮助将不胜感激,我在网上寻找解决方案,但找不到有效的解决方案.谢谢!

Any help on this would be highly appreciated, I looked for solutions online but couldn't find any that worked. Thanks!

推荐答案

在处理动态页面(例如/blog/[slug] .jsx )时,您需要使用 getStaticPaths 除了上面返回的jsx中使用的 getStaticProps router.isFallback?之外.

When handling a dynamic page such as /blog/[slug].jsx you need to use getStaticPaths in addition to getStaticProps and router.isFallback? as you're using in the returned jsx above.

getStaticPaths 捕获传入的可能路径-但是其行为取决于 fallback 键(键的值可以为 true false 阻止" )

getStaticPaths catches incoming possible paths -- its behavior however is dependent on a fallback key (which can have the values true, false, or "blocking")

阻止与服务器端渲染相同,因此它会根据需要为 getStaticPaths 返回的路径生成静态HTML.它被缓存以备将来使用,因此按需生成仅针对每个未由您的 getStaticPaths 函数处理的路径发生一次.如果将 getStaticPaths 设置为 true ,则一小部分动态路径将在构建时呈现,并且如果用户导航到的路径不正确,则会向用户显示加载指示符.在初始构建期间未呈现.对于大型电子商务网站或具有大量动态路径的网站,使用 true 很有用,这样构建过程就不会花费很长的时间才能完成.将 getStaticPaths 设置为 false 将导致在构建过程中未呈现任何路径,如果用户导航到该路径将导致404错误.根据您的需求,以上任何一种方法可能都是最合适的.就是说,重要的是要注意,阻塞" 根本不需要使用 router.isFallback .我还建议研究将 revalidate getStaticProps 一起使用的好处.

Blocking is identical to Server Side Rendering so it generates static HTML on demand for paths not returned by getStaticPaths. This is cached for future use so that this on demand generation only happens once per path not handled by your getStaticPaths function. If you set getStaticPaths to true then a small subset of dynamic paths will be rendered at build time and a loading indicator will be displayed to the user if a path they navigate to isn't rendered during the initial build. Using true is useful for large e-commerce sites or sites with a large number of dynamic paths so that the build process doesn't take a ridiculously long time to complete. Setting getStaticPaths to false will result in any path not rendered during the build process to result in a 404 error if a user navigates to it. Depending on your needs, any of the above methods could be most appropriate. That said, it is important to note that "blocking" does not require the use of router.isFallback at all. I also suggest looking into the benefits of utilizing revalidate with getStaticProps.

以下是使用 getStaticPaths 捕获传入动态路径的示例:

Here is an example of using getStaticPaths to catch incoming dynamic paths:

const AboutSlugsQueryVars: AboutSlugsVariables = {
    order: OrderEnum.ASC,
    field: PostObjectsConnectionOrderbyEnum.SLUG,
    first: 15
};

type DynamicPaths = {
    params:
        | {
                slug: string | Array<string>;
          }
        | never[];
}[];

export async function getStaticPaths(
    ctx: GetStaticPathsContext,
    pathsData: DynamicPaths
) {
    const q = ctx!.defaultLocale;
    console.log(`${q}`)
    const apolloClient = initializeApollo();
    const { data } = await apolloClient.query<AboutSlugs, AboutSlugsVariables>({
        query: ABOUT_SLUGS,
        variables: AboutSlugsQueryVars
    });

    pathsData = [];

    if (
        data &&
        data.aboutslugs !== null &&
        data.aboutslugs.edges !== null &&
        data.aboutslugs.edges.length > 0
    )
        data.aboutslugs.edges.map(post => {
            if (post !== null && post.node !== null && post.node.slug !== null) {
                pathsData.push({ params: { slug: post.node.slug } });
            }
        });

    return {
        paths: pathsData,
        fallback: true
    };
}

有许多方法可以过滤 getStaticPaths ,您还可以使用 GetStaticPathsContext 捕获传入的 locales 以及默认的 locale(如果适用).

There are many approaches to filtering getStaticPaths, you can also use GetStaticPathsContext to catch incoming locales as well as the default locale (if applicable).

这篇关于在npm运行构建的预渲染页面上获取TypeError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆