How to intercept route changes caused by setting a query param value #476
-
Hello, I love using nuqs for manipulating next query params, but I've run into an issue where I'm unable to intercept url changes when query params are updated using the setter method in I'm attempting to run some code like this:In one component, I'm listening for route changes in the router (I'm using the pages router, so const router = useRouter()
useEffect(() => {
const handleRouteChange = (nextPath: string) => {
console.log(nextPath)
// check conditions and optionally block navigation
}
router.events.on('routeChangeStart', handleRouteChange)
return () => {
router.events.off('routeChangeStart', handleRouteChange)
}
}, []) Then in another component, I am using nuqs to update the value of a url param const [param, setParam] = useQueryState(
paramName,
parseAsString.withDefault(defaultValue)
)
const updateParam = (value: string) => {
setParam(value)
} After diving into nuqs, I found that it's not using Is there a workaround for this, or would this be considered a bug in the code? I'll unfortunately have to abandon the library if I can't get a solution to this issue. Thanks so much! versions:
|
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
I replicated your setup, and I do get events. router-events.movHere's the complete page code: import { NextRouter, useRouter } from 'next/router'
import { parseAsInteger, useQueryState } from 'nuqs'
import React from 'react'
declare global {
interface Window {
next?: {
version: string
router?: NextRouter & {
state: {
asPath: string
}
}
}
}
}
export default function Page() {
const [, setCount] = useQueryState('count', parseAsInteger.withDefault(0))
const router = useRouter()
React.useEffect(() => {
const handleRouteChange = (nextPath: string) => {
console.log('router: %s', nextPath)
// check conditions and optionally block navigation
}
router.events.on('routeChangeStart', handleRouteChange)
return () => {
router.events.off('routeChangeStart', handleRouteChange)
}
}, [])
React.useEffect(() => {
const handleRouteChange = (nextPath: string) => {
console.log('nuqs router: %s', nextPath)
// check conditions and optionally block navigation
}
window.next?.router?.events.on('routeChangeStart', handleRouteChange)
return () => {
window.next?.router?.events.off('routeChangeStart', handleRouteChange)
}
}, [])
return <button onClick={() => setCount(c => c + 1)}>Test</button>
} A few things to note:
|
Beta Was this translation helpful? Give feedback.
Hi @franky47 Thanks so much for the timely reply. I've spent several hours on this, and I realized that my use case is actually more specific.
Essentially I'm using router events to display a confirmation modal when a user tries to update the url. The confirmation modal is only rendered when specific conditions are met (in this scenario, when
?willBlockNavigation=true
). The problem was actually caused because the source of truth from nuqs seems to be its own internal state (NOT the url value). As a result, when the nuqs setter method is called, it is removing the router event listener BEFORE the url is updated, which explains why the modal didn't display for me when a user updates another…