reactjs 如何在Next.js中更改路由而不重新渲染?

7fhtutme  于 5个月前  发布在  React
关注(0)|答案(2)|浏览(99)

我创建了一个过滤器,当我点击确认按钮更改网址。
例如,当我点击第1页,输入guesthouse in巴黎时,URL如下所示。

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

字符串
现在我想改变结果时,网址改变。假设当我手动改变查询参数如下,过滤器也应该改变。

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=巴黎-> city=newYork)时,组件重新渲染并重置了我在组件第一次渲染时推送的查询参数。
为什么浅期权不起作用?

uurity8g

uurity8g1#

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)


这很难看,但它和预期的一样工作。一个很好的方法来保持你的路线与你的状态同步。
我建议你把它变成一个效用函数。

a5g8bdjr

a5g8bdjr2#

您可能会看到由于“新”路由导致useRouter的状态更改而导致的状态更改所导致的重新呈现。
一个简单的解决方法是使用Router而不是useRouter。两者的功能相同,因为useRouter只是类的RouterContext
useRouter:https://github.com/vercel/next.js/blob/canary/packages/next/client/router.ts#L127-L129
路由器:https://github.com/vercel/next.js/blob/canary/packages/next/next-server/lib/router/router.ts#L505
请注意,您需要更改组件树中的父组件,使其也使用Router而不是useRouter

相关问题