I created a simple React hook to update the search params:
import { useSearchParams, usePathname, useRouter } from "next/navigation";
export const useParams = () => {
const searchParams = useSearchParams();
const router = useRouter();
const pathname = usePathname();
const setParams = (key: string, value: string) => {
const params = new URLSearchParams(searchParams);
params.set(key, value);
router.replace(`${pathname}?${params}`);
};
return { setParams };
};
Then I use it in a client component:
export const Pagination = () => {
const { setParams } = useParams();
const handleChangePageSize = (size: number) => {
setParams("pageSize", size.toString());
};
const handleSetPage = (pageNumber: number) => {
setParams("pageNumber", pageNumber.toString());
};
// ... More code
My issue is that after handleChangePageSize
is called and the pageSize
param is set with a value, when then later handelSetPage
is called, it's not aware of the pageSize
, which was set. To be more precise, the hook lags by one change. If I remove the router.replace
inside the hook (for testing), I can see that if I call handleChangePageSize
twice, for example with values of 3, and then 6, then when I call handleSetPage
, the params will have the value of 3, therefore it lags by one.
Why does it lag and how can I correct my hook?
Try making a state to track the param
import { useState } from "react";
import { useSearchParams, usePathname, useRouter } from "next/navigation";
export const useParams = () => {
const searchParams = useSearchParams();
const router = useRouter();
const pathname = usePathname();
const [params, setParamsState] = useState(new URLSearchParams(searchParams));
const setParams = (key: string, value: string) => {
const updatedParams = new URLSearchParams(params);
updatedParams.set(key, value);
setParamsState(updatedParams);
router.replace(`${pathname}?${updatedParams.toString()}`);
};
return { setParams };
};
page.tsx
const { setParams } = useParams();
const handleChangePageSize = (size: number) => {
setParams('pageSize', size.toString());
};
const handleSetPage = (pageNumber: number) => {
setParams('pageNumber', pageNumber.toString());
};
<button
onClick={() => {
handleChangePageSize(Math.floor(Math.random() * 100));
}}
>
Set Page Size
</button>
<button
onClick={() => {
handleSetPage(Math.floor(Math.random() * 100));
}}
>
Set Page
</button>