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

RNW styles applied twice when using nextjs app directory with react-native-web with SSR #4270

Open
macrozone opened this issue Feb 29, 2024 · 1 comment

Comments

@macrozone
Copy link

macrozone commented Feb 29, 2024

Environment

System:

  • OS: macOS 14.2.1
  • CPU: (12) arm64 Apple M2 Max
  • Memory: 3.39 GB / 64.00 GB
  • Shell: 5.9 - /bin/zsh

Binaries:

  • Node: 18.19.1 - ~/.nvm/versions/node/v18.19.1/bin/node
  • Yarn: 4.0.1 - ~/.nvm/versions/node/v18.19.1/bin/yarn
  • npm: 10.2.4 - ~/.nvm/versions/node/v18.19.1/bin/npm

Reproduction

here is a link to a repository that reproduces the problem:

https://github.com/macrozone/styled-components-rnw-reproduction

I added multiple scenarios.

Best run it locally (check it out, then yarn dev or npm run dev) and go to localhost:3000

it shows links to multiple scenarios. The first one shows the actual problem reported here.

The others are cases work correctly (but are probably not what you want or have).

Steps to reproduce (as in the repo above)

I wrote these before creating the reproduction, so it may be easier to checkout the repo.

  • create a nextjs application
  • add react-native-web and styled-components
  • create a layout file like this:
import { StyleProvider } from "./StyleProvider";

export const metadata = {
  title: "Next.js",
  description: "Generated by Next.js",
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <StyleProvider>{children}</StyleProvider>
      </body>
    </html>
  );
}

and StyleProvider like this:

"use client";

import { useServerInsertedHTML } from "next/navigation";
import React, { useState } from "react";
import { StyleSheet } from "react-native";
import { ServerStyleSheet, StyleSheetManager } from "styled-components";

export const StyleProvider = ({ children }: { children: React.ReactNode }) => {
  const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet());

  useServerInsertedHTML(() => {
    // @ts-ignore
    const rnwStyle = StyleSheet.getSheet();
    const styledComponentsStyle = styledComponentsStyleSheet.getStyleElement();
    styledComponentsStyleSheet.instance.clearTag();

    return (
      <>
        <style
          dangerouslySetInnerHTML={{ __html: rnwStyle.textContent }}
          id={rnwStyle.id}
        />
        {styledComponentsStyle}
      </>
    );
  });

  if (typeof window !== "undefined") return <>{children}</>;

  return (
    <StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
      {children}
    </StyleSheetManager>
  );
};
  • then create a Test component
"use client";
import styled from "styled-components/native";
import { View, Text } from "react-native";
import { useEffect, useState } from "react";

const Base = styled(View)`
  padding: 20px;
  margin: 20px;
  background-color: #f0f0f0;
  border: 1px solid red;
`;

const TheText = styled(Text)`
  color: green;
`;

export const Test = () => {
  const [show, setShow] = useState(false);

  useEffect(() => {
    setShow(true);
  }, []);

  return show ? (
    <Base>
      <TheText>Hello</TheText>
    </Base>
  ) : (
    <TheText>no show</TheText>
  );
};


and finally page.tsx:

import { Test } from "./Test";

export default Test;

Expected Behavior

Bildschirmfoto 2024-02-29 um 17 00 49

Actual Behavior

Bildschirmfoto 2024-02-29 um 17 01 04

Context & more information

  1. When looking at the SSR rendered result, you see that it shows no show in green, so SSR contains indeed styling information
  2. to see the "Actual Behavior", remove the <StyleProvider /> in the layout. This results in the SSR result beeing unstyled though, which is not what we want
  3. The Problem does not happen if you use react-native's styleSheets. There both SSR result and local rendering are consistent, so it looks like it has to be a styled-components problem, not a ReactNativeWeb problem
  4. the problem happens if Styled-components mount on the client, but not on the server
  5. extracting the Styled-components styles in the StyleProvider does nothing, but i kept it in the example for further reference. It was not clear to me whether to add it or not.
  6. the problem is similar to what is described here Css provided to a component overridden by dynamically generated css necolas/react-native-web#1367
@macrozone
Copy link
Author

update: added a link to a reproduction repo https://github.com/macrozone/styled-components-rnw-reproduction

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

1 participant