'How to change route without re-rendering in Next.js?
I created a filter that when I clicked confirmed button changes url.
For example, When I clicked page 1 and place type guesthouse in paris, url looks like this below.
http://localhost3000/findstay?page=1&per=10&place_type=guest_house&city=paris
Now I want to changed the result when url changed. Suppose when I manually changed query params like below, filter should also changed.
http://localhost3000/findstay?page=1&per=10&place_type=hotel&city=newYork
In order to do this. I created a file name findstay in pages folder and created findstay-filter component inside of components folder.
import React from "react";
import FindstayFilter from "@/components/findstay/findstay-filter";
interface IFindstayProps { };
const Findstay: React.FC<IFindstayProps> = () => {
return <FindstayFilter />;
};
export default Findstay;
All the logic I have explained are written inside of FindstayFilter component.
And this is the code that pushses url when FindstayFilter is rendered.
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)));
}, []);
As you can see I used {shallow: true} option and url does not changes only query params are changed. However when I changed one of queries manually (city=paris -> city=newYork), component re-renders and reset query params that I pushes when component renders first time.
Why shallow option is not working?
Solution 1:[1]
The shallow
option is working. Its goal is to not let your browser navigate away. But it definitely triggers a state update, which triggers the re-render.
Surely, you've had occasions where you really need it to trigger that state update so you can use updated query param values.
Now, how do you update the URL without triggering a re-render? You use window.history
, not Next router.
So, instead of this:
router.push({
pathname: `/findstay`,
query: {
page: _page,
per: 10,
plage_type: _placeType,
city: _city,
}
}, undefined,
{ shallow: true })
You would do this:
const newUrl = `/findstay?page=${_page}&per=10&place_type=_placeType&city=_city`
window.history.replaceState({ ...window.history.state, as: newUrl, url: newUrl }, '', newUrl)
It's ugly, but it works as expected. A really nice way to keep your route synced with your state.
I'd recommend you turn it into a utility function.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Nick Rameau |