2

I'm trying to achieve a dynamic routing structure, using Prismic within my Next.js app. Essentially, I have a page, mysite.com/landing-page for example, that I'm able to route to within my [uid] template, using { uid } = params in my getServerSideProps function. However, I want to allow users to visit that same page via a subdirectory, such as mysite.com/sacramento-ca/landing-page. The research that I've done seems to indicate that I can create a content relationship within my Prismic repository that specifies the location from which the page could also be referenced (sacramento-ca being the example here), and then reference those in my query, and pass that to the page template. However, I can't figure out how to make that happen.

My pages directory is structured like this:

├── [uid]
│   └── index.tsx
├── index.tsx
├── products
│   └── [uid].tsx
├── projects
│   └── index.tsx
├── promos
│   ├── [id].tsx
│   └── index.tsx
└── sitemap
    └── index.tsx

..and overall this works just fine for top level pages. But 1. how can I query the category in getServerSideProps and how would I name and nest the page templates? I read this question/answer as well, and that seems like it's on the right track, but I'm not sure how to make it happen. Here is the code for my [uid] template as well, in case that's helpful.

import React from 'react';

import { SEO } from 'components/seo/SEO';
import { SliceZone } from 'components/slice-zone/SliceZone';

import { client, queryWithProducts } from '../../lib/prismic';

export const Page = ({ document }: any) => {
  const slices = document;
  if (!slices) return null;

  const { meta_title, meta_description, meta_keywords, social_image } = document;

  return (
    <>
      <SEO
        title={meta_title}
        description={meta_description}
        keywords={meta_keywords}
        banner={social_image.url}
      />
      <SliceZone slices={slices} />
    </>
  );
};

export default Page;

export const getServerSideProps = async ({ params, query }: any) => {
  console.log(query)
  const { uid } = params;
  const { data: document } = await client.getByUID('landing', uid, queryWithProducts);

  return {
    props: {
      document,
    },
  };
};

1 Answer 1

1

You're on the right track, you can use a dynamic catch-all route.

You'll need to rename your folder to [...uid], which will make params.uid return and array rather than a string.

// [...uid]/index.tsx

export const getServerSideProps = async ({ params, query }: any) => {
    const { uid } = params; 
    // When navigating to /sacramento-ca/landing-page `uid` will 
    // be an array containing ['sacramento-ca', 'landing-page']

    // Add logic to retrieve data based on array values

    return {
        props: {
            document,
        },
    };
};
Sign up to request clarification or add additional context in comments.

4 Comments

Okay, I've gotten the basics of this working. The only thing that I'm struggling with is that I can't figure out how to parse the array values to get the data from Prismic. Essentially, sacramento-ca/interior-doors works, but when I visit just interior-doors I get an error, saying that my Prismic client expects a string literal.
Since the location, sacramento-ca, is optional you should adapt the code to support that - you could check for the uid array length and query the data from Prismic differently based on it.
What I wrote for now is something akin to this: const parsed = _.isArray(uid) ? uid[1] : uid[0] and then I pass parsed to my Prismic client. Is that what you mean?
Actually, uid will always be an array. You need to check whether to pass the second element or the first based on the number of items it contains.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.