Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Next.js dynamic route error: The provided path `page-name` does not match the page: `/[slug]`

I am attempting to use [slug].js to render pages adjacent to index.js via getStaticProps and getStaticPaths. Upon navigation to a page using the dynamic route I get a mismatch error. This error occurs even when the provided path does in fact match the page slug and page props content.

When the index.js is duplicated and renamed to page-name.js (e.g. about.js) the page renders fine, so I believe the issue lies with how I am using getStaticPaths. In reality, I do not fully comprehend the relationship between getStaticProps and getStaticPaths. Is there some mapping which occurs to allow the engine to look up the appropriate props given whatever path in the map?

Index.js

import Link from 'next/link';
import { getPageDataBySlug } from '../lib/api';

export default function Page(pageData) {
  const page = pageData;
  return (
    <>
      <h1>document title is: {page.documentTitle}</h1>
      <Link href="/[slug]" as="/about">
        <a>
          <h5>Link to About</h5>
        </a>
      </Link>
    </>
  );
}

export async function getStaticProps() {
  const props = await getPageDataBySlug('home');
  return {
    props
  };
}

[slug].js

import Link from 'next/link';
import { getPageDataBySlug, getApiDataPaths } from '../lib/api';

export default function Page(pageData) {
  const page = pageData;

  return (
    <>
      <h1>document title is: {page.documentTitle}</h1>
      <Link href="/" as="/">
        <a>
          <h5>Link to Home</h5>
        </a>
      </Link>
    </>
  );
}

// Only grab the entry for this page
export async function getStaticProps({ params }) {
  const props = await getPageDataBySlug(params.slug);
  return {
    props
  };
}

export async function getStaticPaths() {
  const apiDataPaths = await getApiDataPaths();
  return {
    paths: apiDataPaths?.map(({ slug }) => `${slug}`) ?? [],
    fallback: false
  };
}

getStaticProps returns the correct page content

{
  "title": "About",
  "slug": "about",
  "description": "About page description",
  "documentTitle": "Pithy Compelling Headline",
  "article": {
    "content": [[Object], [Object]],
  }
}

getApiDataPaths() returns

[
  { slug: 'about' },
  { slug: 'another-page' },
  { slug: 'yet-another' }
]

And the getStaticPaths() map returns paths as an array:

[
  'about',
  'another-page',
  'yet-another'
]

What am I missing here? Should getStaticPaths only the path of the current page?

FWIW I am using Contentful as the API and that's working perfectly.

like image 203
Neil Baller Avatar asked Sep 16 '20 20:09

Neil Baller


1 Answers

Next Js Docs Helped out in finding the error. This is where you went wrong. You were passing in an array of objects in this format:

[{id:1}, {id:2}]

when the getStaticPaths was expecting this:

[
    { params: { id: '1' } },
    { params: { id: '2' } }
]

Solution:

  export async function getStaticPaths() {

  const apiDataPaths = await getApiDataPaths();
  // Empty arr to build new paths
  const newPaths = [];
  // Add params to every slug obj returned from api
  for (let slug of apiDataPaths) {
    newPaths.push({ params: { ...slug } });
  }
  // Return paths to render components
  return {
    paths: newPaths,
    fallback: true
  };
}

You can also consider cleaning the data on the serverside.

like image 109
Gandalf Avatar answered Sep 24 '22 20:09

Gandalf