Rahul
Rahul

Reputation: 849

How to solve "Cannot read property 'title' of undefined" using NextJS prerendering?

I am prerendering this page for a specific post on my Next.js application:

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

Everything works fine on npm run dev but when I run npm run build I get this error:

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

I believe the error is due to the <Head> component from Next where I'm trying to set the <title> dynamically through {postData.title}. I'm getting the data as a prop from getStaticProps().

I'm not sure what mistake I'm making but I do wonder if I have to create that <Head> component outside the /pages directory.

Upvotes: 4

Views: 1167

Answers (1)

leerob
leerob

Reputation: 3122

Let me explain how Next.js will “fallback” when requesting any of the other posts after the initial build. There are two options to choose from: blocking and true.

  • fallback: blocking (preferred) – when a request is made to a page that hasn’t been generated, Next.js will server-render the page on the first request. Future requests will serve the static file from the cache.
  • fallback: true – when a request is made to a page that hasn’t been generated, Next.js will immediately serve a static page with a loading state on the first request. When the data is finished loading, the page will re-render with the new data and be cached. Future requests will serve the static file from the cache.

Unless you want to serve that static loading shell, followed by loading your post on the client-side, I would change from true to blocking. That will solve your issue!

Upvotes: 4

Related Questions