javascripturlroutesnext.jscatch-all

Next.js catch-all / as routing


I'm migrating a site over from Gatsby using WP as a headless CMS. I didn't build the original site so I'm inheriting a load of code I'm not familiar with.

I'm using a /pages/listing/[slug].js component to generate individual listings for this client. I am fetching paths by querying all the slugs for their listings in getStaticPaths, and using the slug to query the db to get data for the page using getStaticProps. All good so far. Only issue right now is I've been told the client wants to retain their urls as they currently are - eg listing/experience/location/product-name-here (where product-name-here is the slug I fetched from the CMS), but I have only figured out how to do listing/product-name-here.

My failed approaches so far have been to:

I have wondered if there is some way to access the URL, but the only thing I have come across is so far is useRouter and since that's a hook I am unable to use it outside of the component itself.

I have left code snippets out because I feel like my approach is fundamentally wrong rather than this being an annoying error I am getting.

Edit The problem was eventually solved by having fallback set to true, and setting a hell of a lot of optional chaining for anything handling API related data - as well as empty defaults on all props. My gut feeling is still that this is not the correct 'Next' way to handle this, but the project was migrated over from Gatsby and kind of shoehorned in so I just needed to get it working.


Solution

  • Use pages/listing/[...slug].js as filename, and then return from the getStaticPaths an object like this:

      return {
        paths: [
          { params: { slug: ["path1"] } },
          { params: { slug: ["path2"] } },
          { params: { slug: ["deeper", "path"] } }
        ],
        fallback: false
      };
    

    This means that following addresses are working:

    Then you can access the slug as an array in getStaticProps from the context context.params.slug. That would contain ["path1"], ["path2"] or ["deeper", "path"] depending on the page visited.

    You can try it out in the sandbox below:

    https://codesandbox.io/s/confident-microservice-lu2jl?file=/pages/listing/%5B...slug%5D.js