Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

routeChangeComplete event called on page load for routes with params #11639

Open
anthonyshort opened this issue Apr 3, 2020 · 18 comments
Open

Comments

@anthonyshort
Copy link
Contributor

anthonyshort commented Apr 3, 2020

Describe the bug

When ASO is enabled and you navigate to pages with params the routeChangeComplete is called. On page load:

This is a problem because routeChangeComplete isn't called when loading pages that don't have parameters. This inconsistency makes things difficult.

In my case I'm trying to call analytics events on route change and page load. The page view event is called on page load (using an effect) but then the routeChangeComplete is immediately called which fires the page view again.

To Reproduce

Reproduction example here

Steps to reproduce:

  1. Start the server
  2. Go to / and see that route change is NOT logged
  3. Add any query param, e.g. /?id=1. Reload the page and notice route change is called
  4. Go to /posts/1 and see that route change is logged on page load
  5. Add getInitialProps to _app and this doesn't happen any more

Expected behavior

I would expect either:

  1. Route change is always called on page load while ASO is enabled.
  2. Route change is not called on page load for pages with params

(I'd also not expect the query object to be empty, but that's probably a separate issue)

Screenshots

N/A

System information

  • OS: macOS
  • Browser (if applies) Chrome
  • Version of Next.js: 9.3.4

Additional context

N/A

@anthonyshort
Copy link
Contributor Author

@timneutkens I can probably take a look into it myself if I can get pointed in the right direction.

@Yankovsky
Copy link

Same problem here.
routeChangeComplete event is called because this evaluates to true

(hydrateProps && hydrateProps.__N_SSG && location.search))

Additional condition was probably firstly introduced here 45832e4
I don't know what hydrateProps.__N_SSG means, probably Not Static Site Generation?

@Yankovsky
Copy link

Yankovsky commented Jul 15, 2020

I've tried local development and static export and in both cases data.nextExport was false and __N_SSG was true.

@Yankovsky
Copy link

Similar problem #15082

@Yankovsky
Copy link

Maybe someone from core team can explain what was intended here.

@valse
Copy link
Contributor

valse commented Aug 4, 2020

Hi, check it out this discussion #12306 about avoid double analytics views on page load

@valse
Copy link
Contributor

valse commented Aug 4, 2020

However this is a big problem when you must trigger something on change routing only: I have this need and at the moment I can't find a workaround to skip the first "bad" routeChangeComplete trigger :(

@Yankovsky
Copy link

@valse that's great, but it is a workaround. It would be great to understand reasons behind the code and to fix root problem.

kodiakhq bot pushed a commit that referenced this issue Nov 11, 2020
Use useRouter over Router and add a workaround for the issue #11639
@ypresto
Copy link

ypresto commented Jun 17, 2021

Still exists in next v10.2.3

@mi-na-bot
Copy link
Contributor

This issue exists on routeChangeStart as well with next 11.1.0 and makes the router hooks really difficult to use!

@tpreusse
Copy link
Contributor

tpreusse commented Oct 18, 2021

Have you considered listening to router.isReady?

See #11639 (comment)

Outdated Solution
  useEffect(() => {
    if (router.isReady) {
      track()
    }

    const onRouteChangeComplete = (url, { shallow }) => {
      track()
    }
    router.events.on('routeChangeComplete', onRouteChangeComplete)
    return () => {
      router.events.off('routeChangeComplete', onRouteChangeComplete)
    }
  }, [])

@GiancarlosIO

This comment has been minimized.

@yousefcisco
Copy link

@tpreusse Thanks, that worked for me!

@barberdt
Copy link

barberdt commented Nov 10, 2021

Adding my recent experience here as well. After seeing wildly inaccurate "page view" events in our event tracking system I determined it was because of this same issue. Completely agnostic of query params, routeChangeComplete was firing on the initial page load for all of our SSG pages but not for our SSR pages. I too have now determined the above router.isReady to be the best workaround.

To echo what's already been said here, the primary issue here is that, based on code and documentation, I still can't tell what's "expected" here vs. what may be a bug in the router. I guess my expectation would be that routeChange<anything> wouldn't fire at all on initial page load for any type of page, but rather only once user interaction or my own code has triggered a history change.

@and-poulsen
Copy link

Is there any news on this?

@mgr34
Copy link

mgr34 commented Aug 17, 2022

Is there any news on this issue? And could I not just use useRef and update the ref.current property each time, and only track if ref.current !== url?

@tpreusse
Copy link
Contributor

tpreusse commented Aug 18, 2022

@yousefcisco watchout Next v12.2 changed the behaviour again: #37593 — in our case with middleware and incremental ssg pages we no longer got routeChangeComplete events for the initial page view.

New solution:

let lastTrackedPath
const track = path => {
  // avoid double tracking
  // - in case next router becomes ready and triggers a routeChangeComplete
  if (path === lastTrackedPath) {
    return
  }
  lastTrackedPath = path
  // call to analytics api
}

const Track = () => {
  useEffect(() => {
    if (router.isReady) {
      track(router.asPath)
    }
  }, [router.isReady])
  useEffect(() => {
    const onRouteChangeComplete = (asPath) => {
      track(asPath)
    }
    router.events.on('routeChangeComplete', onRouteChangeComplete)
    return () => {
      router.events.off('routeChangeComplete', onRouteChangeComplete)
    }
  }, [])
  return null
}

// render <Track /> in _app.js

@shuding maybe it's a bug that routeChangeComplete is no longer triggered since v12.2 for SSG pages in some circumstances. To be safe and more feature proof we will now listen to isReady changes and routeChangeComplete and deduplicate with a custom check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests