NextJS navigation takes too long
Unanswered
Fire ant posted this in #help-forum
Fire antOP
I am not providing a code snippet because this is a problem I've got on some projects I worked at last month. For some reason, Navigations using nextjs useRouter() and <Link> takes some seconds both in dev and production. I would like to know what are the reasons behind it, what can make my pages navigation to take this much time? As if I use loading.tsx file, it take some time to go to the route and display the loading UI. It's like my project is stucked waiting for the push or replace function to be triggered.
15 Replies
Fire antOP
I tried using both prefetch true and false. Does this prop exist for useRouter() as well?
prefetch doesnt work in dev and slow navigation times because the route is rendered and then you get redirected(slow cause coldstarts), not the other way around. Shoudn't be a problem in production.
Fire antOP
I got it, so maybe If I set prefetch to false and push my code to production, maybe the delay is gone and It can display the loading UI faster
thank you guys
No, it doesn't work like that, prefetching prefetches the link on page load, you'd wanna turn it off in places like logout buttons but otherwise it doesn't affect the behaviour of fetching the page first and then redirecting, does that make sense?
Fire antOP
Yes, it makes sense. But then why is the navigation taking too long both in dev and production ?
try without loading.tsx and just manually wrap your async component with suspense
if u have deeply nested routes loading.tsx could be problematic
Does normally loading the page take long?
Fire antOP
My application is basicly a web chat app.
It has a route /chat/{id} and clicking some chat at the list redirect the user to /chat/{id}. The problem is not the API fetching, it is really fast, the problem is that de replace() function execution from next useRouter takes too long to finish execution. I click some chat on the list and it take more than 2 seconds to navigate to the new route with ID. if I reload the page it loads fast. At the moment I am not displaying any loading component, neither using loading.tsx or <Suspense>.
It has a route /chat/{id} and clicking some chat at the list redirect the user to /chat/{id}. The problem is not the API fetching, it is really fast, the problem is that de replace() function execution from next useRouter takes too long to finish execution. I click some chat on the list and it take more than 2 seconds to navigate to the new route with ID. if I reload the page it loads fast. At the moment I am not displaying any loading component, neither using loading.tsx or <Suspense>.
I have another app that has the same problem in production as well. I have a page with a table of data, and when I try to update some route param(e.g page) using replace() from useRouter it takes too long to update the param in the route and do not even display the loading.tsx UI.
Just display the new data fetched suddenly
do you have a minimal reproduction repository?
Fire antOP
I can send a code snippet from page.tsx
export default async function ChatPage({ params }: { params: { id: string } }) {
const token = await getIdToken({ cookies })
if (!token) {
return redirect('/auth/login')
}
const [persona, chats, initialMessages, pendingJobs] = await Promise.all([
API.personas.get({ idPersona: params.id }),
API.chats.list({ token }),
API.chats.messages.list({
idPersona: params.id,
direction: 'after',
token,
}),
API.chats.messages.listPending({ token }),
])
const PEDING_JOBS_MAP = new Map(
pendingJobs.map(job => [job.id_persona, job.job_type]),
)
const hasMessage = chats.some(chat => chat.id === persona.id)
const mappedChats = chats
.map(chat => {
const matchingPendingJobType = PEDING_JOBS_MAP.get(chat.id)
if (matchingPendingJobType) {
return {
...chat,
lastMessage: {
...chat.lastMessage,
content:
matchingPendingJobType === 'MESSAGE'
? 'Typing...'
: 'Sure, coming right up',
},
}
}
return chat
})
.sort((a, b) => b.lastMessage.timestamp - a.lastMessage.timestamp)
const mappedMessages = initialMessages
console.log('persona ->', persona)
if (!hasMessage) {
mappedChats.unshift({
id: persona.id,
name: persona.name,
photo: persona.photo,
nickname: persona.nickname,
lastMessage: {
id: Date.now().toString(),
content: persona.greeting,
timestamp: Date.now(),
},
})
}
return (
<Chat
chats={mappedChats}
persona={persona}
initialMessages={mappedMessages}
initialPersona={params.id}
pendingJobs={pendingJobs}
/>
)
}