Reputation: 383
Say I have the following files in my /pages folder. If I wanted to use the exact same template for the cats/[slug] and dogs/[slug] routes (but not fish) how would I do that? Right now I have duplicates of the file...
index.js
cats.js
dogs.js
fish.js
/cats
[slug].js
/dogs
[slug].js
/fish
[slug].js
Upvotes: 1
Views: 2152
Reputation: 159
I know this is an old question but you can use "Dynamic Routes" for this. With dynamic routes, predefined routes take precedence over dynamic routes. For dynamic routes to work with statically generated pages the slug page will need to define a list of paths by using getStaticPaths
.
Since predefined routes take precedence over dynamic routes to have a unique page under fish
you would either need to define that page explicitly or setup a different "[slug]" page under a fish
directory.
So cats.js
dogs.js
fish.js
will render at domain.com/cats/
, domain.com/dogs/
, domain.com/fish/
while the dynamic route will render (or match) at domain.com/cats/athing/
, domain.com/dogs/anotherthing/
, domain.com/fish/anythingelse/
etc...
getStaticPaths
will need to pass two params that match the name of the dynamic path directory and slug.
Add a "dynamic" directory in the top level of the pages directory for the animal route and the slug inside like:
[animal]/[slug].js
So the pages directory looks like this:
index.js
cats.js
dogs.js
fish.js
[animal]/[slug].js
Inside [slug].js
getStaticPaths
will need to pass both the [animal]
and [slug]
values in order to create content that is only available under certain top level pages.
A simplified static example would look like this:
export async function getStaticPaths() {
return {
paths: [
{ params: { animal: 'cats', slug: 'athing' } },
{ params: { animal: 'dogs', slug: 'anotherthing' } },
{ params: { animal: 'fish', slug: 'anythingelse' } }
],
fallback: false, // can also be true or 'blocking'
}
}
An example of this in Typescript with data fetching may look like this, where getAllSlugPathsWithAnimal
returns an array of objects shaped like this: { animal: 'dogs', slug: 'anotherthing'}
export const getStaticPaths: GetStaticPaths = async () => {
const slugPathsWithAnimal: AllSlugPathsWithAnimal[] = await getAllSlugPathsWithAnimal();
const paths = slugPathsWithAnimal.map((slugAndAnimal) => ({
params: { animal: slugAndAnimal.animal, slug: slugAndAnimal.slug },
}));
return {
fallback: false,
paths,
};
};
more info on dynamic routes: https://nextjs.org/docs/routing/dynamic-routes more info on data fetching: https://nextjs.org/docs/basic-features/data-fetching/get-static-paths
Upvotes: 0
Reputation: 7924
You can define a component in the components
folder and use it from there maybe?
components/Animal.jsx
const Animal = () => {
// component here
};
export default Animal;
pages/cats/[slug].jsx
import Animal from '../components/Animal';
const Cat = () => {
return (
<Animal
kind="cat"
{...otherAnimalProps}
/>
);
};
export default Cat;
Upvotes: 1