next.js: Next 12.3.1 breaks smooth-scrolling, change made in 12.3.1-canary.4, woks in 12.3.1-canary.3 and before

Verify canary release

  • I verified that the issue exists in the latest Next.js canary release

Provide environment information

Operating System: Platform: darwin Arch: x64 Version: Darwin Kernel Version 21.6.0: Sat Jun 18 17:07:25 PDT 2022; root:xnu-8020.140.41~1/RELEASE_X86_64 Binaries: Node: 16.13.0 npm: 8.1.0 Yarn: 3.2.3 pnpm: N/A Relevant packages: next: 12.3.1-canary.3 eslint-config-next: N/A react: 0.0.0-experimental-8951c5fc9-20220915 react-dom: 0.0.0-experimental-8951c5fc9-20220915

What browser are you using? (if relevant)

No response

How are you deploying your application? (if relevant)

No response

Describe the Bug

@timneutkens @cramforce The following commit completely disables smooth-scrolling- https://github.com/vercel/next.js/pull/40642. We use the following custom hook here to trigger the scroll-behaviour we want. We do not have anything else like a global css which sets the scroll-behaviour on html.

The scroll-behaviour becomes non-deterministic in version 12.3.1-canary.4, the previous version 12.3.1-canary.3 works perfectly. The latest release 12.3.1 is also affected.

import { MittEmitter } from '@app/render-utils';
import { useEffect } from 'react';

/**
 * The scrolling behavior is always set to smooth, when a page mounts.
 * On route change, the scrolling behavior switches to auto before it snaps back to smooth.
 *
 * Note:
 * Do not use the nextJs hook "use-router" in this custom hook; constant re-renders get executed;
 * Unfortunately, it seems there are some bugs in the router implementation (asPath / hash-change).
 *
 * Instead, the nextJs router events object from the _app component is given as an argument.
 */

export const useSmoothScroll = (events: MittEmitter) => {
  const setSmoothScroll = (isSmooth: boolean) => {
    document.documentElement.style.scrollBehavior = isSmooth
      ? 'smooth'
      : 'auto';
  };

  useEffect(() => {
    setSmoothScroll(true);

    const handleRouteChangeStart = () => setSmoothScroll(false);
    const handleRouteChangeComplete = () => setSmoothScroll(true);

    events.on('routeChangeStart', handleRouteChangeStart);
    events.on('routeChangeComplete', handleRouteChangeComplete);

    return () => {
      events.off('routeChangeStart', handleRouteChangeStart);
      events.off('routeChangeComplete', handleRouteChangeComplete);
    };
  }, []);
};

Can you please provide feedback on how to enable scroll-behaviour using the hook again? Thx!

Expected Behavior

Identical behaviour like in 12.3.1-canary.3

Link to reproduction

I will not create a reproducer for things y break; and smooth-scrolling is something which broke a few times in the past.

To Reproduce

Use the hook from above in _app.

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Reactions: 10
  • Comments: 18 (17 by maintainers)

Commits related to this issue

Most upvoted comments

@wyattjoh Here is a video with your reproducer in action illustration the problem. I adjusted the height of the sections to make it clear. Imagine when you have larger pages such as blog posts or a e-commerce pages showing dozen of items, changing a route causes a smooth transition to the top, which is really annoying, and this has to be immediate.

https://user-images.githubusercontent.com/301689/205177206-ac9f05bf-2a71-49b3-a19e-a09dc4206f5f.mov

Thx!

@timneutkens I disabled the hook, and configured scrolling with css. The result was really not the same, compared with the hook enabled using a nightly version of Next right before the change landed. For the next two weeks I’m traveling without any device on hand, but I can provide a reproducer afterwards. Thx for looking into that!