首页 > 解决方案 > 如何使用 NextJS 预渲染解决“无法读取未定义的属性 'title'”?

问题描述

我正在为我的 Next.js 应用程序上的特定帖子预呈现此页面:

import Head from 'next/head';
import Link from 'next/link';
import client from '../../lib/apollo/client'
import POSTS_WITH_SLUGS from '../../lib/queries/allposts'
import POST from '../../lib/queries/post'
import styles from '../../styles/Home.module.css';
import blogStyles from '../../styles/Blog.module.css';

export default function Post({ postData }) {
    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>
    )
}

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

    const { data } = await client.query({
        query: POSTS_WITH_SLUGS
    });

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

}


export async function getStaticProps({ params }) {
    const { data } = await client.query({
        query: POST,
            variables: {
                id: params.slug,
                idType: 'SLUG'
            }
        });

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

一切正常,npm run dev但是当我运行时出现npm run build此错误:

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

我相信这个错误是由于<Head>我试图<title>通过{postData.title}. 我从getStaticProps().

我不确定自己犯了什么错误,但我想知道是否必须在目录<Head>之外创建该组件。/pages

标签: javascriptreactjsnext.jsserver-side-rendering

解决方案


让我解释一下 Next.js 在初始构建后请求任何其他帖子时如何“回退”。有两个选项可供选择:blockingtrue

  • fallback: blocking(首选)– 当对尚未生成的页面发出请求时,Next.js 将在第一个请求时服务器渲染该页面。未来的请求将从缓存中提供静态文件。
  • fallback: true– 当对尚未生成的页面发出请求时,Next.js 将立即为第一个请求提供加载状态的静态页面。数据加载完成后,页面将使用新数据重新渲染并被缓存。未来的请求将从缓存中提供静态文件。

除非您想提供该静态加载外壳,然后在客户端加载您的帖子,否则我会从 更改trueblocking. 这将解决您的问题!


推荐阅读