简体   繁体   English

Next.js:一页匹配根'/'和动态路由'/param'

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

I have a website as a single page that is using Next.js.我有一个使用 Next.js 的单页网站。 I have the home page on route / that show a list of products.我在 route /上有主页,显示产品列表。 The code of this page is located in pages/index.js .该页面的代码位于pages/index.js中。 Each product has an id so I can jump to it using /#product-id .每个产品都有一个id ,所以我可以使用/#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 .为了使它对 url 更友好,我使用product-id作为路径中的第二个参数来复制这种行为: /product-id

What I do is simply looking on the product-id param using useRouter() :我所做的只是使用useRouter()查看product-id参数:

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

And then scroll to the element with this id using js :然后使用js滚动到具有此 id 的元素:

document.getElementById(selectedProductId ).scrollIntoView()

So I to change my script name from /pages/index.js to /pages/[product-id].js .所以我将我的脚本名称从/pages/index.js/pages/[product-id].js

So now the route /1234 work has expected but if I go to / I get error 404.所以现在路线/1234工作已经预料到,但如果我 go 到/我得到错误 404。

So has someone an idea how I can match / and /param using one js file?那么有人知道如何使用一个js文件匹配//param吗?

Nextjs has file system based routing, so if you remove /pages/index.js of course you will get an 404 error. Nextjs 有基于文件系统的路由,所以如果你删除/pages/index.js当然你会得到一个404错误。 Also /pages/index.js and /pages/[product-id].js will render two separate pages.此外/pages/index.js/pages/[product-id].js将呈现两个单独的页面。

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.要回答您的问题,如果可以使用 nextjs 在一个文件中匹配//[productId]之类的两条路由,我认为这是不可能的,但是通过使用特定于您的用例的浅层路由可以实现类似的结果。

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.因此,对于您的用例,我建议使用浅层路由,除非您想在两个页面中呈现相同的组件只是为了获取product-id或想要使用 hash URL。

You can make product-id a query string parameter and update it using shallow-routing.您可以将product-id查询字符串参数并使用浅路由对其进行更新。 Here is an example,这是一个例子,

Keep /pages/index.js保留/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.浅层路由将允许更改 URL 而无需再次运行数据获取方法,即getStaticPropsgetServerSideProps Which will make the updated query and pathname available without changing the state.这将使更新的查询和路径名可用,而无需更改 state。 Read more about it nextjs docs .阅读更多关于它的 nextjs 文档

Option 1: Extract the shared code选项 1:提取共享代码

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.您可以将 Page 组件提取到单独的文件中,然后将其同时导入/pages/index.js/pages/[product-id].js ,因此代码不会重复。

Option 2: Use experimental rewrites feature选项 2:使用实验性rewrites功能

Assuming you have /pages/[product-id].js you can show this page when a user requests / .假设您有/pages/[product-id].js您可以在用户请求/时显示此页面。

You would need to add next.config.js .您需要添加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.因此,当用户请求/他们会看到/[product-id]的内容,只是带有空的产品 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 .请注意,目前 rewrite 不支持自动渲染动态页面,因此您必须禁用动态页面的自动渲染

You can do that by adding getServerSideProps to /pages/[product-id].js .您可以通过将getServerSideProps添加到/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]]).通过将参数包含在双括号 ([[...slug]]) 中,可以使捕获所有路由成为可选的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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