簡體   English   中英

在 npm run build 的預渲染頁面上獲取 TypeError

[英]Getting TypeError on prerendering page in npm run build

我在我的 Next.js 應用程序上預呈現此頁面:

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屬性給出錯誤:

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) 上,而其他所有內容都可以正常加載。

我正在使用 GraphQL 創建查詢:

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 文件導入這個 function 並使用 getStaticProps() function 中的數據。

對此的任何幫助將不勝感激,我在網上尋找解決方案但找不到任何有效的解決方案。 謝謝!

在處理/blog/[slug].jsx等動態頁面時,除了getStaticPropsrouter.isFallback?之外,您還需要使用getStaticPaths嗎? 正如您在上面返回的 jsx 中使用的那樣。

getStaticPaths捕獲傳入的可能路徑——然而,它的行為取決於fallback鍵(可以具有值truefalse"blocking"

Blocking與服務器端渲染相同,因此它會根據getStaticPaths未返回的路徑的需要生成 static HTML 。 這被緩存以供將來使用,因此這種按需生成僅在您的getStaticPaths function 未處理的每個路徑中發生一次。 如果將getStaticPaths設置為true ,那么將在構建時呈現一小部分動態路徑,並且如果在初始構建期間未呈現用戶導航到的路徑,則會向用戶顯示加載指示器。 使用true對於大型電子商務站點或具有大量動態路徑的站點很有用,這樣構建過程就不會花費很長的時間來完成。 getStaticPaths設置為false將導致在構建過程中未呈現任何路徑,如果用戶導航到它,則會導致 404 錯誤。 根據您的需要,上述任何方法都可能是最合適的。 也就是說,重要的是要注意"blocking"根本不需要使用router.isFallback 我還建議研究使用revalidategetStaticProps的好處。

下面是使用getStaticPaths捕獲傳入動態路徑的示例:

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 (如果適用)。

如果有人在使用yarn export遇到這個或類似問題,解決方案是將 fallback 設置為 false。 這為我修復了所有頁面呈現錯誤。

來自 Next.js 文檔:

// This function gets called at build time
export async function getStaticPaths() {
  // Call an external API endpoint to get posts
  const res = await fetch('https://.../posts')
  const posts = await res.json()

  // Get the paths we want to pre-render based on posts
  const paths = posts.map((post) => ({
    params: { id: post.id },
  }))

  // We'll pre-render only these paths at build time.
  // { fallback: false } means other routes should 404.
  return { paths, fallback: false }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM