How to detect completion of router.refresh() #58520
Replies: 3 comments
-
This seems to be related to #49810 |
Beta Was this translation helpful? Give feedback.
-
Base on the discussion given by @ptts, I've made a custom hook to return a import { useRouter } from "next/navigation";
import { useEffect, useState, useTransition } from "react";
/**
* Wrapper around `router.refresh()` from `next/navigation` `useRouter()` to return Promise, and resolve after refresh completed
* @returns Refresh function
*/
export function useRouterRefresh() {
const router = useRouter()
const [isPending, startTransition] = useTransition()
const [resolve, setResolve] = useState<((value: unknown) => void) | null>(null)
const [isTriggered, setIsTriggered] = useState(false)
const refresh = () => {
return new Promise((resolve, reject) => {
setResolve(() => resolve)
startTransition(() => {
router.refresh()
})
})
}
useEffect(() => {
if (isTriggered && !isPending) {
if (resolve) {
resolve(null)
setIsTriggered(false)
setResolve(null)
}
}
if (isPending) {
setIsTriggered(true)
}
}, [isTriggered, isPending, resolve])
return refresh
} Usage function App() {
const refresh = useRouterRefresh()
const handle = () => {
refresh()
.then(() => {
// Do something when refresh is done
})
}
return ...
} |
Beta Was this translation helpful? Give feedback.
-
Well for my scenario is I will call However, if you change your idea, you can just pass some unique things to your client components. export default async function Home(props: {
params: Promise<{ locale: string }>;
}) {
const params = await props.params;
const { locale } = params;
const data = await fetchData();
return (
<div>
<RSC data={data.serverData}> </RSC>
<ClientComponent data={data.clientData}></ClientComponent>
</div>
);
} You actually could just pass a unique thing, like export default async function Home(props: {
params: Promise<{ locale: string }>;
}) {
const params = await props.params;
const { locale } = params;
const data = await fetchData();
return (
<div>
<RSC data={data.serverData}> </RSC>
{/* Add Date.now() to tell client we have been changed */}
<ClientComponent
data={data.clientData}
refreshKey={Date.now()}
></ClientComponent>
</div>
);
} And then everything is settled, do anything you want after the route is refreshed: const resetTaskList = () => {
setTaskListData([]);
setPageNum(2);
window.scrollTo({ top: 0, behavior: "smooth" });
};
useEffect(() => {
resetTaskList();
}, [refreshKey]); |
Beta Was this translation helpful? Give feedback.
-
I am facing a challenge related to the
router.refresh()
method. In the recent updates, it appears that the ability to listen to router events has been removed, which has impacted how we can detect the completion of a page refresh initiated byrouter.refresh()
.In my current project, I need to know when
router.refresh()
has completed its process. The methodrouter.refresh()
does not return a promise or have a callback, making it difficult to know exactly when the refresh process has completed.In standard scenarios, where data updates post-refresh, we can use various techniques like checking for changes in state, global context, or even direct DOM observations. However, these methods fall short in cases where the refreshed page's data remains unchanged - a situation that's not uncommon in many real-world applications.
Looking for a potential solutions, thank you!
Beta Was this translation helpful? Give feedback.
All reactions