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

Nextjs Render Error caused by Scroll Trigger being enabled #603

Open
robert-j-webb opened this issue Nov 26, 2024 · 2 comments
Open

Nextjs Render Error caused by Scroll Trigger being enabled #603

robert-j-webb opened this issue Nov 26, 2024 · 2 comments

Comments

@robert-j-webb
Copy link

robert-j-webb commented Nov 26, 2024

Repro case, on NextJS 15

Hi, I tracked down the cause of this error in the console:

installHook.js:1 Warning: Extra attributes from the server: style Error Component Stack
    at body (<anonymous>)
    at html (<anonymous>)
    at RootLayout [Server] (<anonymous>)
    at RedirectErrorBoundary (redirect-boundary.js:57:27)
    at RedirectBoundary (redirect-boundary.js:107:26)
    at NotFoundErrorBoundary (not-found-boundary.js:29:27)
    at NotFoundBoundary (not-found-boundary.js:116:26)
    at DevRootNotFoundBoundary (dev-root-not-found-boundary.js:33:26)
    at ReactDevOverlay (ReactDevOverlay.js:38:27)
    at HotReload (hot-reloader-client.js:327:29)
    at Router (app-router.js:229:25)
    at ErrorBoundaryHandler (error-boundary.js:76:27)
    at ErrorBoundary (error-boundary.js:185:32)
    at AppRouter (app-router.js:613:38)
    at ServerRoot (app-index.js:117:27)
    at Root (app-index.js:122:26)

I'm using NextJS 14.1.2, app router, gsap/react: 2.1.1

The code that causes this error is just:

'use client';

import { useGSAP } from '@gsap/react';
import gsap from 'gsap';
import { ScrollTrigger } from 'gsap/all';
import { useRef } from 'react';

gsap.registerPlugin(useGSAP, ScrollTrigger);

export default function Page() {
  const container = useRef<HTMLDivElement>(null);

  useGSAP(
    () => {
      const tl = gsap.timeline({
        scrollTrigger: {
          trigger: `.space-y-8`,
          start: 'top top',
          end: 'bottom top',
          scrub: true,
        },
        defaults: { ease: 'none' },
      });
    },
    { scope: container },
  );
  return <div className="space-y-8" ref={container}></div>;
}

I wanted to see if I could fix the problem, so I took a look at the source code and found some code that looked like a potential cause.

In the enable function, body style is modified twice link to code

let bodyStyle = _body.style,
	border = bodyStyle.borderTopStyle,
	AnimationProto = gsap.core.Animation.prototype,
	bounds, i;
AnimationProto.revert || Object.defineProperty(AnimationProto, "revert", { value: function() { return this.time(-0.01, true); }}); // only for backwards compatibility (Animation.revert() was added after 3.10.4)
bodyStyle.borderTopStyle = "solid"; // works around an issue where a margin of a child element could throw off the bounds of the _body, making it seem like there's a margin when there actually isn't. The border ensures that the bounds are accurate.
bounds = _getBounds(_body);
_vertical.m = Math.round(bounds.top + _vertical.sc()) || 0; // accommodate the offset of the <body> caused by margins and/or padding
_horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0;
border ? (bodyStyle.borderTopStyle = border) : bodyStyle.removeProperty("border-top-style");

I found that if I removed the two lines that modify body style, then the error went away.

So now it becomes:

let AnimationProto = gsap.core.Animation.prototype,
	bounds, i;
AnimationProto.revert || Object.defineProperty(AnimationProto, "revert", { value: function() { return this.time(-0.01, true); }}); // only for backwards compatibility (Animation.revert() was added after 3.10.4)
bounds = _getBounds(_body);
_vertical.m = Math.round(bounds.top + _vertical.sc()) || 0; // accommodate the offset of the <body> caused by margins and/or padding
_horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0;

Now I'm not sure what the suggested fix is. Probably you need to make sure your bounds calculation doesn't occur until after render.

You can wrap client side only checks like this in:

if(typeof document !== undefined) {

}

And then it won't run on the server, which is what is causing this error.

@robert-j-webb
Copy link
Author

Note, I am also seeing it on Next 15 canary

installHook.js:1 A tree hydrated but some attributes of the server rendered HTML didn't match the client properties. This won't be patched up. This can happen if a SSR-ed Client Component used:

- A server/client branch `if (typeof window !== 'undefined')`.
- Variable input such as `Date.now()` or `Math.random()` which changes each time it's called.
- Date formatting in a user's locale which doesn't match the server.
- External changing data without sending a snapshot of it along with the HTML.
- Invalid HTML tag nesting.

It can also happen if the client has a browser extension installed which messes with the HTML before React loaded.

https://react.dev/link/hydration-mismatch

  ...
    <HotReload assetPrefix="">
      <ReactDevOverlay onReactError={function} state={{nextId:1, ...}} dispatcher={{...}}>
        <DevRootNotFoundBoundary>
          <NotFoundBoundary notFound={<NotAllowedRootNotFoundError>}>
            <NotFoundErrorBoundary pathname="/" notFound={<NotAllowedRootNotFoundError>} notFoundStyles={undefined} ...>
              <RedirectBoundary>
                <RedirectErrorBoundary router={{...}}>
                  <Head>
                  <link>
                  <RootLayout>
                    <html lang="en" className="[color-sch...">
                      <body
                        className={"overflow-y-scroll bg-gray-1100 bg-[url('/grid.svg')] pb-36"}
-                       style={{}}
                      >
                  ...
        ...

Repro case: https://replit.com/@robertwebb10/GSAP-Nextjs-Body-style-error-reprodution?v=1

@robert-j-webb robert-j-webb changed the title Nextjs Render Error caused by Scroll Trigger being imported Nextjs Render Error caused by Scroll Trigger being enabled Nov 26, 2024
@jackdoyle
Copy link
Member

I believe this was addressed here:
https://gsap.com/community/forums/topic/43281-hydration-error-in-nextjs-15/

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

2 participants