JPM
JPM

Reputation: 383

reusing a template in the nextjs pages folder

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

Answers (2)

Ian Roberts
Ian Roberts

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

Gokhan Sari
Gokhan Sari

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

Related Questions