Nextjs router causing useEffect to re-render
Answered
Carpenter ant posted this in #help-forum
Carpenter antOP
Hi, I'm encountering an issue with Next.js's next/navigation router. I have a set of
useEffects in my component, and for some reason calling router.replace causes one of the effects to run a second a time, and in some cases just run infinitely. This causes a set of elements to play its transition animation twice (or just get stuck running infinitely) every time the user clicks a button that changes the activity.Answered by Ray
because
try using
https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating#windowhistoryreplacestate
router.replace() will navigate to the page but not adding new entry to the browser history. so the useEffect run again when the page load.try using
window.history.replaceState() instead if you want to update the url without navigationwindow.history.replaceState(null, '', `${window.location.pathname}?${urlParams.toString()}`)https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating#windowhistoryreplacestate
13 Replies
Carpenter antOP
const [selectedActivity, setSelectedActivity] = useState<Activity | null | undefined>(undefined)
const [customNames, setCustomNames] = useState<CustomNames>({})
const router = useRouter()
...
const changeActivity = useCallback((activity: Activity | null) => {
setSelectedActivity(activity)
const urlParams = new URLSearchParams(window.location.search);
if (activity) {
urlParams.set('activity', activity.id)
}
else {
urlParams.delete('activity')
}
// set query params to reflect the selected activity, or remove them if null
router.replace(`${window.location.pathname}?${urlParams.toString()}`)
}, [router])useEffect(() => {
if (calloutSet) {
// read query params to see if activity is specified
const urlParams = new URLSearchParams(window.location.search);
const activityId = urlParams.get('activity');
const activity = calloutSet.activities.find(activity => activity.id == activityId)
changeActivity(activity ?? null)
// also populate custom names
const customNames: CustomNames = {}
// Convert urlParams.entries() to an array and iterate over it
Array.from(urlParams.entries()).forEach(([key, value]) => {
const imageId = parseInt(key)
if (isNaN(imageId)) return
const imageReference = calloutSet.allImages.find(image => image.id == imageId)
if (!imageReference) return
// If the name is the same as the default, remove it from the custom names
if (imageReference.name != value) {
customNames[imageId] = value
}
})
setCustomNames(customNames)
// if the callout set is not custom, attempt to load the custom names from local storage
if (!urlParams.has('isCustom') || urlParams.get('isCustom') != 'true') {
const customNamesJson = localStorage.getItem(`${calloutSet.id}.customNames`)
if (customNamesJson) {
setCustomNames(JSON.parse(customNamesJson))
}
}
}
}, [calloutSet, changeActivity])By commenting out the
router.replace line in changeActivity, the erroneous re-rendering stopped (I still want the URL to update though). Removing calloutSet and changeActivity from the dependency list also worked, but ESLint would start yelling at me and it causes issues with my navbar search bar. I just want the useEffect to run once whenever the activity changes, and that's it. Any ideas?Wool sower gall maker
dont know which next js version u are running just found this
@Wool sower gall maker dont know which next js version u are running just found this
Carpenter antOP
im using 14.0.1
@Carpenter ant im using 14.0.1
Wool sower gall maker
maybe try to update and it fixes your problem
Carpenter antOP
alright lemme see
@Wool sower gall maker maybe try to update and it fixes your problem
Carpenter antOP
nope, issue still persists
Carpenter antOP
bump
@Carpenter ant Hi, I'm encountering an issue with Next.js's next/navigation router. I have a set of `useEffect`s in my component, and for some reason calling `router.replace` causes one of the effects to run a second a time, and in some cases just run infinitely. This causes a set of elements to play its transition animation twice (or just get stuck running infinitely) every time the user clicks a button that changes the activity.
because
try using
https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating#windowhistoryreplacestate
router.replace() will navigate to the page but not adding new entry to the browser history. so the useEffect run again when the page load.try using
window.history.replaceState() instead if you want to update the url without navigationwindow.history.replaceState(null, '', `${window.location.pathname}?${urlParams.toString()}`)https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating#windowhistoryreplacestate
Answer
@Carpenter ant THANK YOU ðŸ™
did it work for you?
Carpenter antOP
yup