简体   繁体   中英

Next.js: one page that match root '/' and dynamic route '/param'

I have a website as a single page that is using Next.js. I have the home page on route / that show a list of products. The code of this page is located in pages/index.js . Each product has an id so I can jump to it using /#product-id .

To make it more url friendly I replicate this behaviour using the product-id as a second param in the route like that: /product-id .

What I do is simply looking on the product-id param using useRouter() :

const selectedProductId = useRouter().query['product-id']

And then scroll to the element with this id using js :

document.getElementById(selectedProductId ).scrollIntoView()

So I to change my script name from /pages/index.js to /pages/[product-id].js .

So now the route /1234 work has expected but if I go to / I get error 404.

So has someone an idea how I can match / and /param using one js file?

Nextjs has file system based routing, so if you remove /pages/index.js of course you will get an 404 error. Also /pages/index.js and /pages/[product-id].js will render two separate pages.

To answer your question, if it is possible to match two routes like / and /[productId] in one file using nextjs I don't think that is possible however similar results can be achieved by using shallow routing specific to your use case.

So for your use case, I suggest using shallow routing unless you want to render the same component in both pages just to get the product-id or want to make use of hash URLs.

You can make product-id a query string parameter and update it using shallow-routing. Here is an example,

Keep /pages/index.js

import { useRouter } from 'next/router';

const router = useRouter()

// when want to change the productId call
router.push('/?productId=1234', undefined, { shallow: true })

// call the scrollToView inside a useEffect hook
useEffect(() => {
    const productId = router.query.productId
    // get the element using the productId above then call scrollIntoView()
})

// if using useEffect with the dependency router.query.productId, 
// when you change the productId once and scroll up and try to change to the same -
// productId again it will not scroll to view, hence not using the dependency array
// at all

To explain more on what shallow routing does

Shallow routing will allow the change of URL without running the data fetching methods ie getStaticProps or getServerSideProps again. Which will make the updated query and pathname available without changing the state. Read more about it nextjs docs .

Option 1: Extract the shared code

You could extract a Page component to a separate file and then import it in both /pages/index.js and /pages/[product-id].js , so the code is not duplicated.

Option 2: Use experimental rewrites feature

Assuming you have /pages/[product-id].js you can show this page when a user requests / .

You would need to add next.config.js .

module.exports = {
  experimental: {
    async rewrites() {
      return [
        { source: "/", destination: "/[product-id]" },
      ];
    }
  }
}

So, when a user requests / they would see the content of /[product-id] , just with the empty product id.

Note, that at the moment rewrite doesn't support auto-rendered dynamic pages, so you have to disable auto-rendering for the dynamic page .

You can do that by adding getServerSideProps to /pages/[product-id].js .

export async function getServerSideProps() {
  return {
    props: {},
  }
}

Optional catch all routes

Catch all routes can be made optional by including the parameter in double brackets ([[...slug]]).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM