The getStaticPaths() keeps throwing the 404 page and I'm guessing that is because of the function getAllPostIds() which is meant to return an array of objects. I'm making use of typescript, I've declared the array of objects but I'm not sure how to use the replace method on the id
interface ArrObj {
params: {
id: string;
}
}
let arrObj: ArrObj[];
export function getAllPostIds() {
const fileNames = fs.readdirSync(postsDirectory);
return fileNames.map(fileName => {
return {
params: {
id: fileName.replace(/\.md$/, '')
}
}
})
}
export function getPostData(id) {
const fullPath = path.join(postsDirectory, `${id}.md`)
const fileContents = fs.readFileSync(fullPath, 'utf8')
const matterResult = matter(fileContents)
return {
id,
...matterResult.data
}
}
export async function getStaticPaths(){
const paths = getAllPostIds();
return{
paths,
fallback: false
}
}
export async function getStaticProps({ params }) {
const postData = getPostData(params.id)
return {
props: {
postData
}
}
}
Add the fallback props as true or blocking. Seting it as false will return a 404 page because the requested path was not generated during build time.
return{
paths,
fallback: true
}
Related
My page is working correctly, but When I look in the console I'm getting 5, 404 errors on fetch request. not sure where this is coming from..
I only get these 404s in production. Nothing in development.
Page File Structure
live site: https://real-fake-store.vercel.app/
github repo: https://github.com/Haviles04/real-fake-store
Here is the code I think it's coming from.
export async function getStaticPaths() {
const { products } = await import("../../../data/products/allData.json");
return {
paths: products.map((item) => {
const productId = item.id;
const productName = item.title
.toLowerCase()
.replace(/\s/g, "")
.toString();
const catName = item.category.name.toLowerCase().toString();
return {
params: {
catName,
productId: `${productId}=${productName}`,
},
};
}),
fallback:false,
};
}
export async function getStaticProps({ params }) {
const { categoryItems } = await import(
`../../../data/products/${params.catName}Data.json`
);
const pageProduct = categoryItems.find(
(item) => item.id === parseInt(params.productId)
);
return {
props: {
pageProduct,
},
};
}
and I'm getting this in the console
This was fixed by adding passHref to the LINK component that was directing to the page.
Error: A required parameter (plantName) was not provided as a string in getStaticPaths for /plants/[plantName]/streaming-data/[panel]
above is the error showing up.My folder structure is plants > [plantName] > streamin-data > [panel]
I have defined getStaticPaths inside of [plantName] using statically available list of plant names. And also tried doing the same in [panel]
For example two panels are there "a" and "b" and one plantname, so inside of [plant] slug file i created static paths like plantname/a and plantname/b but still the error came up.
// [panel].js
export async function getStaticPaths() {
const paths = [];
const listOfPlants = plantsList.map((plant) => ({
plantName: plant.id,
}));
const listOfPanels = [
'heat-transfer',
'asset-tags',
'test-tags',
'flow-meter-board',
'pi-data',
'all-tags',
'analytics',
'manual-logs',
'data-quality',
];
listOfPlants.forEach((plantName) => {
listOfPanels.forEach((panel) => {
paths.push({ params: { plantName, panel } });
});
});
return {
paths,
fallback: false, // can also be true or 'blocking'
};
}
export const getStaticProps = async ({ params }) => ({
props: {
panel: params.panel,
plantName: params.plantName,
},
});
// [plantName].js
export const getStaticPaths = async () => ({
paths: (() => {
const plants = plantsList;
const params = plants.map((plant) => ({ params: { plantName: plant.id } }));
return params;
})(),
fallback: true,
});
export const getStaticProps = async ({ params }) => ({
props: {
panel: params.plantName,
},
});
It seems like the plantName value in your paths array is not a string.
listOfPlants is an array of objects, so when you map over it you need to destructure each item to access plantName, like so:
listOfPlants.forEach(({ plantName }) => {
I have a problem with the 'getStaticPaths' function. When I try to get a dynamic display with a parameter it shows me as error: Error: A required parameter (slug) was not provided as an array in getStaticPaths for /posts/[...slug]
In My utils.js file got this function read the files
export function getPostsFiles() {
const postsDirectory = path.join(process.cwd(), "posts");
return fs.readdirSync(postsDirectory);
}
In my page [...slug]
export function getStaticProps(context) {
const { params } = context;
const { slug } = params;
const postData = getPostData(slug);
return {
props: {
post: postData,
},
revalidate: 600,
};
}
export function getStaticPaths() {
const postFilenames = getPostsFiles();
const slugs = postFilenames.map((fileName) => fileName.replace(/\.md$/, ""));
const parameters = slugs.map((slug) => ({ params: { slug: slug } }));
return {
paths: parameters,
fallback: true,
};
}
I have the following content structure:
src
|-- content
|-- terms-conditions.html
|-- makeup.html
The terms and conditions page has the following data which I can call
{ seo:
url: "makeup/terms-conditions"
}
I'd like the content of terms-conditions.html to actually show under the url makeup/terms-conditions. I've tried a few times using getStaticPaths to no avail so any guidance would be appreciated. Essentially all of my files will sit one level down from content but I'd like to actually serve them under the URL defined under seo/url
My getStaticPaths code in my [params].tsx file is as follows.
export async function getStaticPaths() {
const posts = getAllPosts(["slug"]);
return {
paths: posts.map((post) => {
return {
params: {
slug: post.slug,
},
};
}),
fallback: false,
};
}
getStaticProps:
export async function getStaticProps({ params }) {
const post = getPostBySlug(params.slug, ["slug", "data"]);
const content = (await post.content) || "";
return {
props: {
post: {
...post,
content,
},
},
};
}
And in my api file I have:
import fs from "fs";
import { join } from "path";
import matter from "gray-matter";
const postsDirectory = join(process.cwd(), "src/content");
export function getPostSlugs() {
return fs.readdirSync(postsDirectory);
}
export function getPostBySlug(slug: string, fields = []) {
const realSlug = slug.replace(/\.html$/, "");
const fullPath = join(postsDirectory, `${realSlug}.html`);
const fileContents = fs.readFileSync(fullPath, "utf8");
const { data, content } = matter(fileContents);
const items = { };
fields.forEach((field) => {
if (field === 'slug') {
items[field] = realSlug
}
if (field === 'data') {
items[field] = data
}
})
return items;
}
export function getAllPosts(fields = []) {
const slugs = getPostSlugs()
const posts = slugs
.map((slug) => getPostBySlug(slug, fields))
return posts
}
I have a problem with the getStaticPaths function.
When I try to get a dynamic display with a parameter it shows me as error: A required parameter (id) was not provided as a string in getStaticPaths for / movies / [id] but if I use the other way above it works. Above all I am the documentation.
import fetch from 'node-fetch';
function MovieSelect({movie}){
return(
<div>
<h1>Test: {movie.name}</h1>
<p>{movie.summary.replace(/<[/]?[pb]>/g, '')}</p>
{movie.image ? <img src={movie.image.medium} /> : null}
</div>
)
}
export async function getStaticPaths(){
const request = await fetch('https://api.tvmaze.com/search/shows?q=batman')
const movies = await request.json()
//const paths = movies.map(movie =>`/movies/${movie.show.id}`)
const paths = movies.map(movie =>({
params: {id: movie.show.id},
}))
return {
paths,
fallback: false
}
}
export async function getStaticProps({params}){
const request = await fetch(`https://api.tvmaze.com/shows/${params.id}`)
const movie = await request.json()
return{
props:{
movie
}
}
}
export default MovieSelect
A required parameter (id) was not provided as a string in getStaticPaths for / movies / [id]
id should be a string as suggested by the error. Upon hitting the api from your browser, you can see that the id is not a string but a number. You need to convert it to string.
params: {id: movie.show.id.toString()},
My problem generated the same error, but I had a different bug.
TL;DR: The name of my file needed to match the key of the slug used in the params object.
In my case, my file name was [postSlug].js. Therefore, the key should have been postSlug inside of getStaticPaths().
// In [postSlug].js
const pathsWithParams = slugs.map((slugs) => ({ params: { postSlug: slug } })); // <-- postSlug is right
const pathsWithParams = slugs.map((slugs) => ({ params: { id: slug } })); // <--- id is wrong
My entire function then looked like this
export async function getStaticPaths() {
const slugs = await getAllBlogSlugs();
const pathsWithParams = slugs.map((slug) => ({ params: { postSlug: slug } }));
return {
paths: pathsWithParams,
fallback: "blocking",
};
}
References:
NextJS.org Get Static Paths
export async function getServerSideProps({ query, locale }) {
const { id } = query;
if (!id) return { notFound: true };
return {
props: {
fallback: true,
query,
locale,
...(await serverSideTranslations(
locale,
["common", "header", "footer"],
nextI18nextConfig
)),
},
};
}