在npm运行构建的预渲染页面上获取TypeError [英] Getting TypeError on prerendering page in npm run build
问题描述
我正在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屋!