I'm trying to add a dynamic table of contents to my blogpage in next.js. The code is running perfectly on my localhost, but as soon as I'm deploying it to vercel I got this error:
TypeError: Cannot read properties of undefined (reading 'content')
at BlogPost (/vercel/path0/.next/server/pages/posts/[slug].js:111:23)
at Jc (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:64:191)
at Mc (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:66:253)
at Z (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:71:89)
at Nc (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:73:98)
at Mc (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:67:131)
at Z (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:71:89)
at Mc (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:70:13)
at Z (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:71:89)
at Nc (/vercel/path0/node_modules/react-dom/cjs/react-dom-server.browser.production.min.js:73:98)
I found out that the build failure is produced by the command .processSync on line 85 (I wrote a comment there). Sadly I'm unable to fix this... Any suggestions and help why this happens?
Here is the full code: ( I delete the grahpcms route when creating the GraphQLClient for safety, so that's not the failure here.)
import { GraphQLClient, gql } from "graphql-request";
import { useRouter } from "next/router";
import { unified } from "unified";
import rehypeParse from "rehype-parse/lib";
import rehypeStringify from "rehype-stringify/lib";
import { visit } from "unist-util-visit";
import parameterize from "parameterize";
const graphcms = new GraphQLClient();
const QUERY = gql`
query Post($slug: String!) {
post(where: { slug: $slug }) {
title
id
content {
html
}
datePublish
coverPhoto {
url
}
datePublish
}
}
`;
const SLUGLIST = gql`
{
posts {
slug
}
}
`;
export async function getStaticPaths() {
const { posts } = await graphcms.request(SLUGLIST);
return {
paths: posts.map((post) => ({ params: { slug: post.slug } })),
fallback: true,
};
}
export async function getStaticProps({ params }) {
const slug = params.slug;
const data = await graphcms.request(QUERY, { slug });
const post = data.post;
return {
props: {
post,
},
};
}
export default function BlogPost({ post }) {
const router = useRouter();
var toc = [];
//Forms the HTML String into a tree that we can add logic too
//Then forms that tree back into html string
const newContent = unified()
.use(rehypeParse, {
fragment: true,
})
.use(() => {
return (tree) => {
visit(tree, "element", (node) => {
if (node.tagName === "h2") {
const id = parameterize(node.children[0].value);
node.properties.id = id;
toc.push({
id: node.properties.id,
title: node.children[0].value,
});
console.log("id", id);
}
});
};
})
.use(rehypeStringify)
//THIS IS WHERE THE DELPLOYMENT FAILS
.processSync(post.content.html)
.toString();
if (router.isFallback) {
return <h2>Loading</h2>;
}
return (
<div>
<header>
<h1>{post.title}</h1>
<img
src={post.coverPhoto.url}
width="100%"
style={{ borderRadius: "1rem" }}></img>
<span>Published: {post.datePublish}</span>
</header>
<main>
<div>
{toc.map(({ id, title }) => {
return (
<li style={{ listStyle: "none" }} key={id}>
<a style={{ fontSize: "1.1rem" }} href={`#${id}`}>
<b> {title}</b>
</a>
</li>
);
})}
</div>
<div
className="blogpost"
dangerouslySetInnerHTML={{ __html: newContent }}
/>
</main>
</div>
);
}
Thank you very much!
CodePudding user response:
I would try to use operator of optional changing like this:
post?.content?.html
Second step is to build project on your computer not to wait for building on vercel and detect another error.
P. S. You can handle undefined props by if statement but only don't forget to place it before main return statement and after all hooks.