【问题标题】:Next.js: one page that match root '/' and dynamic route '/param'Next.js: 匹配根 '/' 和动态路由 '/param' 的一页
【发布时间】:2020-09-17 20:37:05
【问题描述】:

我有一个使用 Next.js 的单页网站。我在路线/ 上有主页,其中显示了产品列表。此页面的代码位于pages/index.js。每个产品都有一个id,所以我可以使用/#product-id 跳转到它。

为了使其对 url 更友好,我使用 product-id 作为路由中的第二个参数来复制此行为,如下所示:/product-id

我所做的只是使用useRouter() 查看product-id 参数:

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

然后使用js滚动到具有此ID的元素:

document.getElementById(selectedProductId ).scrollIntoView()

所以我将脚本名称从 /pages/index.js 更改为 /pages/[product-id].js

所以现在路线 /1234 工作已经预料到,但如果我去 / 我得到错误 404。

那么有人知道如何使用一个js 文件匹配//param 吗?

【问题讨论】:

    标签: javascript reactjs next.js


    【解决方案1】:

    Nextjs 有基于文件系统的路由,所以如果你删除/pages/index.js 当然你会得到一个404 错误。 /pages/index.js/pages/[product-id].js 也将呈现两个单独的页面。

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

    因此,对于您的用例,我建议使用浅层路由,除非您想在两个页面中呈现相同的组件以获取 product-id 或想要使用哈希 URL。

    您可以将product-id 设为查询字符串参数并使用浅路由更新它。这是一个例子,

    保持/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
    

    进一步解释浅层路由的作用

    浅路由将允许更改 URL 而无需再次运行数据获取方法,即 getStaticPropsgetServerSideProps。这将使更新的查询和路径名可用而不更改状态。阅读更多关于它的信息nextjs docs

    【讨论】:

    • 感谢您的精彩解释?我最终将只使用一个简单的查询参数,如/?product-id=123
    • 太好了,如果您在实施它时遇到任何问题,请告诉我。
    【解决方案2】:

    选项 1:提取共享代码

    您可以将页面组件提取到单独的文件中,然后将其导入/pages/index.js/pages/[product-id].js,因此代码不会重复。

    选项 2:使用实验性 rewrites 功能

    假设您有/pages/[product-id].js,您可以在用户请求/ 时显示此页面。

    您需要添加next.config.js

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

    因此,当用户请求/ 时,他们将看到/[product-id] 的内容,只是产品ID 为空。

    请注意,目前 rewrite 不支持自动呈现动态页面,因此您必须禁用动态页面的自动呈现

    您可以通过将getServerSideProps 添加到/pages/[product-id].js 来做到这一点。

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

    【讨论】:

    • 非常感谢这个好主意。不幸的是,我现在不打算使用它,因为它是实验性的;)但我真的很高兴在未来使用它
    【解决方案3】:

    可选捕获所有路线

    可以通过将参数包含在双括号 ([[...slug]]) 中来使捕获所有路由成为可选。

    【讨论】:

    • 这就是答案!一个文件pages/[[...slug]].js 将捕获所有路由,然后你就根本不需要index.js
    猜你喜欢
    • 2021-01-03
    • 2022-11-05
    • 2020-09-08
    • 2020-12-13
    • 2021-11-18
    • 2022-01-10
    • 2022-01-04
    • 2022-11-20
    • 2021-12-17
    相关资源
    最近更新 更多