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

styled-components don't rehyrdate properly in React Server Components #66646

Open
blairmcalpine opened this issue Jun 7, 2024 · 2 comments
Open
Labels
bug Issue was opened via the bug report template. Developer Experience Issues related to Next.js logs, Error overlay, etc. Documentation Related to Next.js' official documentation. linear: next Confirmed issue that is tracked by the Next.js team.

Comments

@blairmcalpine
Copy link

blairmcalpine commented Jun 7, 2024

Link to the code that reproduces this issue

https://github.com/blairmcalpine/styled-components-repro

To Reproduce

  1. Start the application (npm run dev)
  2. Visit localhost:3000 and click the "Green (click to switch)" element. You'll see that the color doesn't change, despite the code properly swapping to a blue style. This is because the blue style is overridden with another green style:
image

This second green style is the result of two conflicting <style> tags generated by styled-components. One is generated on the initial doc request, and the second (and third) are adding during hydration - see the style tags marked with data-styled-version="6.1.11":

image

This can lead to completely incorrect styles of the page, if the second style tag contains different styles than the one in the head. While this issue is primarily with React Streaming and styled-components, we want to raise awareness here as NextJS officially "supports" styled-components, and the supported implementation doesn't work properly.

Current vs. Expected behavior

Expected Behaviour:
I expect styled-components <style> tags that are added later as a part of React Server Component hydration to be properly consolidated with the existing <style> tag.

Current Behaviour:
The <style> tag that is added to the DOM as a part of React Server Component hydration isn't combined with the <style> tag in the head, resulting in conflicting styles. Note that this is using the code from the docs.

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 23.5.0: Wed May  1 20:12:58 PDT 2024; root:xnu-10063.121.3~5/RELEASE_ARM64_T6000
  Available memory (MB): 32768
  Available CPU cores: 10
Binaries:
  Node: 20.12.0
  npm: 10.5.0
  Yarn: 1.22.22
  pnpm: N/A
Relevant Packages:
  next: 14.2.3
  eslint-config-next: 14.2.3
  react: 18.3.1
  react-dom: 18.3.1
  typescript: 5.4.5
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Developer Experience, Documentation

Which stage(s) are affected? (Select all that apply)

next dev (local), next build (local), next start (local), Other (Deployed)

Additional context

I have created a related issue with styled-components here.

@blairmcalpine blairmcalpine added the bug Issue was opened via the bug report template. label Jun 7, 2024
@github-actions github-actions bot added Developer Experience Issues related to Next.js logs, Error overlay, etc. Documentation Related to Next.js' official documentation. labels Jun 7, 2024
@huozhi
Copy link
Member

huozhi commented Jun 19, 2024

Looks like the tag keeps emitted while resolving suspense boundaries and the new styles are inserted later.
You could change the code in style register to only flushing the styles once.

// src/lib/registry.tsx
const flushRef = useRef(false);
  useServerInsertedHTML(() => {
    const styles = styledComponentsStyleSheet.getStyleElement();
    // Flush initial styles
    if (!flushRef.current) {
      flushRef.current = true;
      return <>{styles}</>;
    }
    return null;
  })

I tested a bit comparing to styled-components 6.0.x, it seems like a behavior change that we don't need to insert extra styles anymore and styled-components could manage the incoming styles itself.

@blairmcalpine
Copy link
Author

Thanks for the response @huozhi. Unfortunately this solution doesn't work entirely for more complex use cases, as you get a flash of unstyled content before the suspense boundaries resolve.

@github-actions github-actions bot added the linear: next Confirmed issue that is tracked by the Next.js team. label Jul 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Issue was opened via the bug report template. Developer Experience Issues related to Next.js logs, Error overlay, etc. Documentation Related to Next.js' official documentation. linear: next Confirmed issue that is tracked by the Next.js team.
Projects
None yet
Development

No branches or pull requests

2 participants