How can I prevent a page render until components are able to receive data in a dynamic route?
Answered
English Angora posted this in #help-forum
English AngoraOP
Here is my code:
import React from "react";
import Head from "next/head";
import { useRouter } from "next/router";
import { MainWrapper } from "@/components/layout/MainWrapper";
import ProjectPage from "@/components/ProjectPage";
import { getHeadBoilerPlate } from "@/utils/headBoilerPlate";
import { PROJECT_CONTENT } from "@/consts/projectContent";
// export const dynamic = 'force-dynamic';
/**
* This is component handles rendering pages for individual projects. Based on the
* query prop, it determines which project data to show.
*/
export default function ProjectTemplate() {
const router = useRouter();
/**
* Function to look through all projects and return only one project that
* has the same title as projectTitle. This is so that projects can be hyperlinked
* in the format: .../project/<project title>.
* @param {*} projectTitle
* @returns JSON snippet of the project to render.
*/
const filterProjectMatchingTitle = (projectTitle) => {
var result = PROJECT_CONTENT.filter((obj) => {
return obj.title === projectTitle;
});
return result[0];
};
const projectToRender = filterProjectMatchingTitle(
router.query.slug
);
return (
<>
<Head>
<title>{`Mark Valentino - ${projectToRender?.title}`}</title>
{getHeadBoilerPlate(projectToRender?.description)}
</Head>
<MainWrapper>
{/* Prevents ProjectPage from reading from an object that isn't there. */}
{projectToRender && <ProjectPage data={projectToRender} />}
</MainWrapper>
</>
);
}Answered by English Angora
I solved this issue by refactoring my code to this:
I also renamed the file to [projectTitle].jsx. I guess I'm talking to a wall lol.
import React from "react";
import Head from "next/head";
import { MainWrapper } from "@/components/layout/MainWrapper";
import ProjectPage from "@/components/ProjectPage";
import { getHeadBoilerPlate } from "@/utils/headBoilerPlate";
import { PROJECT_CONTENT } from "@/consts/projectContent";
export const getStaticPaths = async () => {
const paths = PROJECT_CONTENT.map((key) => {
return { params: { projectTitle: key.title } };
});
return { paths, fallback: false };
};
export const getStaticProps = async (context) => {
const projectTitle = context.params.projectTitle;
const project = PROJECT_CONTENT.find((obj) => obj.title === projectTitle);
return { props: { project: project } };
};
export default function ProjectTemplate({ project }) {
return (
<>
<Head>
<title>{`Mark Valentino - ${project.title}`}</title>
{getHeadBoilerPlate(project.description)}
</Head>
<MainWrapper>
<ProjectPage data={project} />
</MainWrapper>
</>
);
}I also renamed the file to [projectTitle].jsx. I guess I'm talking to a wall lol.
4 Replies
English AngoraOP
This code is compilable, and works except for an issue where the the title will at some point say "undefined" in the place of "${projectToRender?.title}". I would like to remove the question mark and the boolean checking if "projectToRender" exists. This is bad for SEO as crawlers will look at what is immediately loaded.
This link preview below will have "undefined" in the title (it is using the code above):
https://mark-valentino.vercel.app/project/Earth%203JS
To my knowledge, I can't use componentDidMount() to fix this.
This link preview below will have "undefined" in the title (it is using the code above):
https://mark-valentino.vercel.app/project/Earth%203JS
To my knowledge, I can't use componentDidMount() to fix this.
English AngoraOP
Chat GPT wasn't helping me. Could it be possible that there is no solution for this?
English AngoraOP
English AngoraOP
I solved this issue by refactoring my code to this:
I also renamed the file to [projectTitle].jsx. I guess I'm talking to a wall lol.
import React from "react";
import Head from "next/head";
import { MainWrapper } from "@/components/layout/MainWrapper";
import ProjectPage from "@/components/ProjectPage";
import { getHeadBoilerPlate } from "@/utils/headBoilerPlate";
import { PROJECT_CONTENT } from "@/consts/projectContent";
export const getStaticPaths = async () => {
const paths = PROJECT_CONTENT.map((key) => {
return { params: { projectTitle: key.title } };
});
return { paths, fallback: false };
};
export const getStaticProps = async (context) => {
const projectTitle = context.params.projectTitle;
const project = PROJECT_CONTENT.find((obj) => obj.title === projectTitle);
return { props: { project: project } };
};
export default function ProjectTemplate({ project }) {
return (
<>
<Head>
<title>{`Mark Valentino - ${project.title}`}</title>
{getHeadBoilerPlate(project.description)}
</Head>
<MainWrapper>
<ProjectPage data={project} />
</MainWrapper>
</>
);
}I also renamed the file to [projectTitle].jsx. I guess I'm talking to a wall lol.
Answer