不刷新页面的情况下更改URL NEXT.JS

52

我正在使用NEXT.JSRedux开发电子商务商店。因此,在产品列表页面上,我有一个带有价格从低到高价格从高到低新品到货的排序下拉菜单。在选择这个选项时,我想要改变URL而不刷新页面,并且需要发生API调用。我尝试使用下面的代码,但它不起作用,页面正在重新加载。

function sortBy(value) {
    router.replace({
        pathname: '/products/'+slug,
        query: { sort: value }
    })

    dispatch(fetchproducts(slug, sort));
}
以上代码只是刷新当前页面并将"sort"参数附加到URL中。那么是否有可能像Flipkart一样无需刷新页面来实现呢?
3个回答

100
通过使用shallow-routing,可以在不重新加载页面的情况下更改URL。可以通过将显式选项对象作为Router.push的第三个参数传递来启用,例如{ shallow: true }。 来自文档
浅路由允许您更改URL而不再次运行数据获取方法,包括getServerSidePropsgetStaticPropsgetInitialProps。 您将通过router对象(由useRouterwithRouter添加)接收更新后的pathnamequery,而不会丢失状态。
例如,以下是如何使用shallow-routing更新/products路径名下的查询参数sortBy的示例。
Router.push({
  pathname: '/products',
  query: { sortBy: 'price' }
}, 
undefined, { shallow: true }
)

但是有一些注意事项:不可能在不同页面之间进行浅层路由(shallow-routing),它仅适用于同一页面URL更改。详情请参阅注意事项部分。

例如,您可以更新页面/product的查询参数,但如果您尝试从/product/product/[slug]进行浅层路由(shallow-routing),则将无法实现,因为它们是两个不同的页面。

// page will reload because shallow-routing not possible between the pages
Router.push('/product', '/product/some-product?sortBy=price', { shallow: true })

我只想在URL中添加?sort=3。当前的URL是http://localhost:3000/products/dfhdf/sgsdg?sort=1。但是页面仍然会重新加载。我已经使用了const router = useRouter() - Jithin Varghese
然后您可以使用 router.push。将第一个参数和第二个参数按原样传递,并提供第三个参数作为带有选项 shallow 为 true 的对象 { shallow: true }。请记住,它仅在同一页面 URL 更改时起作用。 - subashMahapatra
4
我怀疑dfhdf部分是动态路由的路由参数。而且页面看起来像是文件系统中的pages/products/[slug].js。所以你应该使用类似这样的router.pushrouter.push('/products/[slug]?sort=1', '/products/dfhdf?sort=1', { shallow: true} - subashMahapatra
2
是的,那就对了。这是一个动态路由 [...slug].js。感谢您的回复。 - Jithin Varghese
使用页面级别的/[...slug].js文件进行相同的场景 - /page/[...slug].js。我没有遇到任何错误,但它仍然重新加载页面。所以我的路由器是这样的:router.push('/[...slug]?sort=1', '/level1/level2?sort=1', { shallow: true} - Yor
显示剩余2条评论

19

例子:你有一个类似这样的文件夹: posts/[id].js,而你的URL链接是这样的http://something.com/posts/123

你想要添加一个不会刷新页面的查询参数,并且你的URL链接将变成这样:http://something.com/posts/123?param=ok

你所需要做的就是:

const postId = 123;
const param = 'ok';
router.push(
    {
      pathname: `/posts/[id]`,
      query: {
        postId,
        param
      }
    },
    `/posts/${postId}?param=${param}`,
    {shallow: true}
);

谢谢!终于找到了我想要的东西。 - Choose Goose

4

这对我很有用。比useRouter更容易,但选项较少。给了我一个锚链接,这正是我需要的。在NextJS文档中阅读更多。

我的[category].js在useEffect钩子中有一个fetch调用,路由器接收URL参数,进行调用并填充数据。页面不会刷新。

function createSortLink(sortBy) {

    const url = 'https://example.com/products/[category].js';
    url.searchParams.set('sortBy', sortBy);

    return (
        <Link 
          href={url}
          shallow={true}
          >
          {name}
        </Link>
        }
    )
}

1
你能解释一下如何在字符串上设置searchParams字段吗?我不明白它是如何工作的。 - undefined
@ColdDarkness 说得对。它需要是一个URL对象。我已经更新了我的答案。谢谢。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接