如何在Next.js中不重新渲染页面的情况下更改路由?

3

我创建了一个过滤器,当我点击确认按钮时会更改URL。

例如,当我点击第1页并在巴黎选择住宿类型为客栈时,URL如下所示。

http://localhost3000/findstay?page=1&per=10&place_type=guest_house&city=paris

现在我想要当 URL 发生变化时更改结果。假设我手动更改查询参数如下,筛选器也应该随之更改。
http://localhost3000/findstay?page=1&per=10&place_type=hotel&city=newYork

为了实现这一点,我在pages文件夹中创建了名为findstay的文件,并在components文件夹中创建了findstay-filter组件。
import React from "react";
import FindstayFilter from "@/components/findstay/findstay-filter";

interface IFindstayProps { };

const Findstay: React.FC<IFindstayProps> = () => {
  return <FindstayFilter />;
};

export default Findstay;

所有的逻辑都写在FindstayFilter组件内部。

FindstayFilter被渲染时,该代码会推送url。

 useEffect(() => {
    const { city, page, per, placeType } = query;
    const _page = parseInt(page || 1 as any);
    const _city = city || state.cityState; // paris
    const _placeType = placeType || "";

    router.push({
      pathname: `/findstay`,
      query: {
        page: _page,
        per: 10,
        plage_type: _placeType,
        city: _city,
      }
    }, undefined,
      { shallow: true })

    const initialRender = {
      page: _page,
      placeType: _placeType,
      city: _city,
    }
    
    searchAvailableBookingDays(initialRender).then(res => res.json().then(value => setData(value)));
  }, []);

正如您所看到的,我使用了{shallow: true}选项,URL并不改变,只有查询参数发生了改变。然而,当我手动更改其中一个查询时(例如,city=paris -> city=newYork),组件会重新渲染,并重置在组件第一次渲染时推送的查询参数。
为什么浅层渲染选项没有起作用?

你找到解决办法了吗?我们也遇到了同样的问题。 - roka
@roka 看一下我的回答。 - Nick Rameau
非常感谢!与您的回答类似,我们同时解决了这个问题,使用了window.location.replaceState。:) 完全忘记了这个问题在这里,否则也会加上的。 - roka
1个回答

8

shallow选项正在发挥作用。它的目标是不让您的浏览器导航离开当前页面。但它肯定会触发状态更新,从而触发重新渲染。

当您真正需要它来触发状态更新以便您可以使用更新后的查询参数值时,您一定会碰到这种情况。

现在,如何在不触发重新渲染的情况下更新URL呢?您需要使用window.history,而非Next路由器。

因此,您可以使用以下方式:

router.push({
      pathname: `/findstay`,
      query: {
        page: _page,
        per: 10,
        plage_type: _placeType,
        city: _city,
      }
    }, undefined,
      { shallow: true })

你会这样做:
const newUrl = `/findstay?page=${_page}&per=10&place_type=_placeType&city=_city`

window.history.replaceState({ ...window.history.state, as: newUrl, url: newUrl }, '', newUrl)

虽然不美观,但它按预期工作。这是一种非常好的方法,可以使您的路由与状态同步。

我建议将其转换为实用函数。


有没有其他解决方案呢?因为我没有找到任何简单的方法来实现这个。这很奇怪,我以为Next.js在2023年会有相关处理方式。 - Martin Choutka

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