How to provide an array in getStaticPaths? - next.js

I learn nextJS and I try to use dynamic routes with a catch-all route. However I'm running into a basic problem, I'm not sure how to supply the data as an array in getStaticPaths.
This is my current code:
import Link from 'next/link';
function test({ variable }) {
return (
<>
<div>
<h1>{variable.var}</h1>
<Link href="/">
<a>← Back</a>
</Link>
</div>
</>
);
}
export async function getStaticProps({ params }) {
const variable = params.variable;
return {
props: {
variable,
},
};
}
export async function getStaticPaths() {
return {
fallback: false,
paths: [
{
params: {
variable: 'testi',
},
},
],
};
}
export default test
And I'm getting the error:
Error: A required parameter (variable) was not provided as an array in getStaticPaths for /test/[...variable]
Any ideas?
Edit:
Forgot to add, my current file name is [...variable].js

Indeed it was stupid:
paths: [
{ params: { variable: ["testi"] } },
]

Related

nextjs dynamic routes doesn't work with next-i18next

I just added next-i18next in my nextjs project following the official guide and everything seemed to be in order, but when I change the language from default (Italian) to English and I go to the detail of an entity then I get 404. This happens only with the dynamic routes and only with the language that is not the default one.
I am going to show you more details.
My next-i18next.config.js file:
module.exports = {
i18n: {
defaultLocale: "it",
locales: ["it", "en"],
},
};
[id].tsx
//My NextPage component...
export async function getStaticPaths() {
const paths = await projects.find()?.map((_project) => ({
params: { id: _project.id + "" },
}));
return {
paths,
fallback: false,
};
}
export async function getStaticProps({
locale,
...rest
}: {
locale: string;
params: { id: string };
}) {
const project = await projects.findOne({id: rest.params.id})
const seo: Seo = {
//...
};
//This row is not the problem, since it persists even if I remove it. Also I am sure that the project exists.
if (!project?.id) return { notFound: true };
return {
props: {
...(await serverSideTranslations(locale, [
"common",
"footer",
"projects",
])),
seo,
project,
},
};
}
index.tsx (under projects folder)
const Projects: NextPage<Props> = ({ /*...*/ }) => {
//...
const router = useRouter();
return <button onClick={() =>
router.push({
pathname: `/projects/[slug]`,
query: { slug: project.slug },
})
}>Read more</button>
}
Also I get the error Error: The provided 'href' (/projects/[slug]) value is missing query values (slug) to be interpolated properly. when I try to change the language while I am in the detail of the project with the italian language set, but I think I did it right according to this doc. As I said before, instead, if I try to go into the dynamic route after having changed the language to "en" then I go to 404 page.
Do you have any suggestions to solve this problem?
I solved this by updating the mothod getStaticPaths to:
export async function getStaticPaths({ locales }: { locales: string[] }) {
const projects = getProjects({ locale: "it" });
const paths = projects.flatMap((_project) => {
return locales.map((locale) => {
return {
params: {
type: _project.slug,
slug: _project.slug,
},
locale: locale,
};
});
});
return {
paths,
fallback: true,
};
}
So there must be passed the locale into the paths.

Using Next.js Catch All (Spread) Routing to Create Multi-Directory URL Structures

I'm trying to create a multi-directory dynamic URL in Next.js.
A rough example of what I'm trying to accomplish is found here: https://codesandbox.io/s/next-js-forked-5scpgb?file=/page/tools/%5B...path%5D.js.
I'm trying to, for example, create a URL route like 'tools/category-title/tool-slug' based on the seed object provided in the example.
I found the https://nextjs.org/docs/routing/dynamic-routes docs, which notes pages/post/[...slug].js matches /post/a, but also /post/a/b, /post/a/b/c and so on.
However, I've been unsuccessful in trying to get this to work.
Any support would be appreciated!
Code from sandbox repo --
import React from "react";
const toolSeed = [
{
id: 1,
slug: "tool-slug",
category: {
id: 1,
title: "category-title",
}
},
{
id: 2,
slug: "tool-slug-2",
category: {
id: 2,
title: "category-title-2",
},
}
]
export async function getStaticPaths() {
const paths = toolSeed.map((tool) => ({
params: { slug: `${tool.category.title}/${tool.slug}` }, // href={`/${tool.category}/${tool.slug}`}
}));
return {
paths: paths,
fallback: false // render 404 if no match
};
}
export async function getStaticProps({ params }) {
// filter to get the current tool
const tool = toolSeed.filter((obj) => obj.slug === params.slug);
return {
props: { tool },
revalidate: 900 // this tells Next.js to re-generate the page every 15 minutes
};
}
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
export default function Tool ({ tool }) {
console.log('tool')
return (
<></>
)
};

NextJS: getServerSideProps - Is there a problem to use props object with redirect in the same return?

I'm using Next.js with Typescript, and I'm having some troubles to correctly type my props that getServerSideProps would return me. On getServerSideProps, or as I call it, getServerSidePropsImpl, I check user authentication and decide if I give it a redirect or the data for it to initialize. The problem with this is that Typescript doesn't correctly type my props, or give me some errors.
So, i had the idea to :
// /pages/sheet/1.tsx
import React from 'react';
import { GetServerSidePropsContext, InferGetServerSidePropsType } from 'next';
import database from '../../utils/database';
import { sessionSSR } from '../../utils/session';
export default function Sheet1(props: InferGetServerSidePropsType<typeof getServerSidePropsImpl>): JSX.Element {
//...Do some stuff...
return <></>;
}
async function getServerSidePropsImpl(ctx: GetServerSidePropsContext) {
const player = ctx.req.session.player;
if (!player) {
return {
redirect: {
destination: '/',
permanent: false
},
props: {
playerID: 0,
playerInfo: []
}
};
}
const playerID = player.id;
const results = await Promise.all([
database.playerInfo.findMany({
where: {
player_id: playerID
},
select: {
info: true,
value: true
},
})
]);
return {
props: {
playerID,
playerInfo: results[0]
}
};
}
export const getServerSideProps = sessionSSR(getServerSidePropsImpl);
To make sure Typescript would correctly type my props object, I had to put generic values when returning a redirect:
return {
redirect: {
destination: '/',
permanent: false
},
props: {
playerID: 0,
playerInfo: []
}
};
Is there any issues to this approach, giving the amount of props will increase as I make this component?

NextJS - Categories (Tags) - Dynamic Pages

I'm using Next.js with Static Site Generation, and I've created a category (tags) component as shown below:
import Link from "next/link";
export default function CategorySection({ categories }) {
return (
<Wrapper>
<ContentWrapper>
<CategoryWrapper>
{categories.map((category) => {
return (
<>
{category.contentfulMetadata.tags.map((tag) => {
return (
<Link href={`/articles/categories/${tag.id}`}>
<Categories>{tag.name}</Categories>
</Link>
);
})}
</>
);
})}
</CategoryWrapper>
</ContentWrapper>
</Wrapper>
);
}
I would like to be able to create dynamic pages for all tags and show articles only related to the tag.
I have created my [slug].jsx file at the following location: /pages/articles/categories/[slug].jsx
[slug].jsx file below:
import { getArticles, getArticle } from "../../../utils/contentful";
export async function getStaticPaths() {
const data = await getArticles();
return {
paths: data.articleCollection.items.map((article) => ({
params: { slug: article.contentfulMetadata.tags.id },
})),
fallback: false,
};
}
export async function getStaticProps(context) {
const data = await getArticle(context.params.slug);
return {
props: { article: data.articleCollection.items[0] },
};
}
export default function Category({ article }) {
return <h1>{article.contentfulMetadata.tags.name}</h1>;
}
I get the following error when navigation by using the tags on my articles page:
Error: A required parameter (slug) was not provided as a string in getStaticPaths for /articles/categories/[slug]
How can I get it to create dynamic pages using the tags?
Error: A required parameter (slug) was not provided as a string in getStaticPaths for /articles/categories/[slug]
In your getStaticPaths you need to convert slug to string.
params: { slug: article.contentfulMetadata.tags.id.toString() }

Next.js route mismatch in prod build but not in dev

I'm using Next.js and trying to implement incremental static regeneration. My pages structure is:
pages
- [primary]
- article
- [...slug.js]
and my [...slug.js]
import Head from 'next/head'
export default function Article({ post }) {
if (!post) {
return 'loading'
}
const data = post[0];
return (
<div className="container mx-auto pt-6">
<Head>
<title>{`${data.title.rendered}`}</title
</Head>
<main>
<div>{data.content.rendered}</div>
</main>
</div >
)
}
export async function getStaticPaths() {
return {
paths: [{ params: { primary: '', slug: [] } }],
fallback: true,
};
}
export async function getStaticProps({ params }) {
const slug = params.slug[0];
const res = await fetch(`https://.../?slug=${slug}`)
const post = await res.json()
return {
props: { post },
revalidate: 1,
}
}
This works locally when I pass route like: localhost:3000/dance/article/lots-of-dancers-dance-in-unison, it correctly passes the slug and I can query the CMS no problem. But when I run build I get:
Error: Requested and resolved page mismatch: //article /article at normalizePagePath
This is because the static path you are providing for primary is '' (empty).
For empty string value for primary, the static path becomes //article which resolves to /article. This is what the error says.
Though this works in development, it will give the said error in Prod build.
Add a value to the path and it should work!
paths: [{ params: { primary: 'abc', slug: [] } }],

Resources