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 fails in Facebook and TikTok browser #5144

Closed
marianzburlea opened this issue Jan 19, 2023 · 10 comments
Closed

styled-components fails in Facebook and TikTok browser #5144

marianzburlea opened this issue Jan 19, 2023 · 10 comments

Comments

@marianzburlea
Copy link

marianzburlea commented Jan 19, 2023

What version of Remix are you using?

1.11.0

Steps to Reproduce

  • run npx create-remix@latest project-name
  • select: basic, typescript, netlify and n so we can run yarn
  • run yarn add styled-components
  • run yarn add -D @types/styled-components
  • create a basic styled component
import styled from 'styled-components'

const H1 = styled.h1`
  border: 1px solid red;
`

export default function Index() {
  return (
    <div>
      <H1>test</H1>
    </div>
  )
}

update entry.server.tsx with:

import { renderToString } from "react-dom/server";
import { RemixServer } from "@remix-run/react";
import type { EntryContext } from "@remix-run/node"; // or cloudflare/deno
import { ServerStyleSheet } from "styled-components";

export default function handleRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  remixContext: EntryContext
) {
  const sheet = new ServerStyleSheet();

  let markup = renderToString(
    sheet.collectStyles(
      <RemixServer
        context={remixContext}
        url={request.url}
      />
    )
  );
  const styles = sheet.getStyleTags();
  markup = markup.replace("__STYLES__", styles);

  responseHeaders.set("Content-Type", "text/html");

  return new Response("<!DOCTYPE html>" + markup, {
    status: responseStatusCode,
    headers: responseHeaders,
  });
}

inside root.tsx file update the head tag to include styles:

    <head>
        <Meta />
        <Links />
        {typeof document === "undefined"
          ? "__STYLES__"
          : null}
    </head>

and deploy to netlify.

Here is an example project that replicates the issue:
https://github.com/marianzburlea/test-sc

and here is an example of the styled component receiving a red border.
https://steady-pixie-99fc00.netlify.app/

Expected Behavior

actual styles to be displayed

image

Actual Behavior

hydration fails and no styles are applied, when I click on a link from Facebook and Tiktok.

The BIG problem is not facebook messenger, it's how people that click paid ads see the website.

This is the same way users that click on an ad, end up on the website, with no styles.

image

image

@marianzburlea marianzburlea changed the title styled-components fails in Facebook browser styled-components fails in Facebook and TikTok browser Jan 19, 2023
@Xiphe
Copy link

Xiphe commented Jan 20, 2023

Im experiencing similar issues outside of the context you describe.

Basically any hydration error where react is forced to rebuild the <head> will cause the styles of styled-components to be removed. While react itself recovers from this state, styled-components fails to do so.

As mentioned in #5159 I'd say this is not per se a remix bug but an architectural incompatibility as the issue can be reproduced with any react app failing to hydrate the whole document and might also happen to other libraries that inject things into the DOM.

ref: styled-components/styled-components#3924

@Xiphe
Copy link

Xiphe commented Jan 23, 2023

related issue in react: facebook/react#24430

@Xiphe
Copy link

Xiphe commented Jan 23, 2023

I was able to work around the problem by:

  1. downgrading to react@17
  2. ensuring that {typeof document === "undefined" ? "__STYLES__" : null} is rendered at the very end of the <head>

Would still love to use latest react features within my app.

@clgeoio
Copy link

clgeoio commented Jan 24, 2023

+1 to this issue - Kent has responded to this issue here, stating that it is a React issue, which I think is fair enough, but I'm not sure if or when the React team would be doing anything about it.

There's a potential workaround, but it's not great - you can render Remix not at the document level, but within a <div> in the body.
By wrapping in an HTML container you can solve this issue, however it comes at the cost of not being able to use <Meta> or <Links> (mostly).
You can somewhat work around this, only sending Links and Meta on the server render and forgoing meta and link changes on the client routing.

entry.client.tsx:

import { RemixBrowser } from '@remix-run/react';
import { hydrateRoot } from 'react-dom/client';

hydrateRoot(document.getElementById('root')!, <RemixBrowser />);

entry.server.tsx (an example using React 18 streams):

import { ServerRoot } from './root.server';

export default async function handleRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  remixContext: EntryContext,
) {
  const stream = await renderToReadableStream(
    <ServerRoot
      location={remixContext.staticHandlerContext.location}
      loaderData={remixContext.staticHandlerContext.loaderData}
      routeModules={remixContext.routeModules}
      matches={remixContext.staticHandlerContext.matches}
    >
      <RemixServer context={remixContext} url={request.url} />
    </ServerRoot>,
  );

  return new Response(stream, {
    status: responseStatusCode,
    headers: responseHeaders,
  });
}

ServerRoot.tsx:

const ServerRoot = ({
  children,
  ...rest
}) => {
  return (
    <html lang="en">
      <head>
        <V1Meta {...rest} />
      </head>
      <body>
        <div id="root">
          {children}
        </div>
      </body>
    </html>
  );
};

Where V1Meta is the Meta component from Remix, but takes the params from props rather than hooks (as the context is not created yet)

The root.tsx does not contain any <html> tags and doesn't play allow any information in the head to be changed client-side.

@Xiphe
Copy link

Xiphe commented Jan 24, 2023

Thanks for sharing. I was also tinkering around with rendering the remix app into a sub-element of the page but gave up because it caused too many things I love about remix to stop working.

As with the "who's problem is this": Yeah the issue lays between React and Styled Components. But Remix on the one hand made the architectural decision to work on the whole document which surfaces the problem and on the other hand advertises styled-components to work in remix apps (which it does but at the cost of react@18).

@clgeoio
Copy link

clgeoio commented Jan 24, 2023

I have created a proposal / discussion for this issue #5244 - give it an upvote!

@Xiphe
Copy link

Xiphe commented Feb 2, 2023

@kiliman figured out how to do this with the current tools and for me it solves the styled-components issues: #5244 (comment)

@kiliman
Copy link
Collaborator

kiliman commented Feb 2, 2023

@Xiphe awesome... glad it resolved the styled-components issue for you.

@github-actions
Copy link
Contributor

This issue has been automatically marked stale because we haven't received a response from the original author in a while 🙈. This automation helps keep the issue tracker clean from issues that are not actionable. Please reach out if you have more information for us or you think this issue shouldn't be closed! 🙂 If you don't do so within 7 days, this issue will be automatically closed.

@github-actions github-actions bot added the needs-response We need a response from the original author about this issue/PR label Apr 19, 2023
@github-actions
Copy link
Contributor

This issue has been automatically closed because we didn't hear anything from the original author after the previous notice.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Apr 26, 2023
@MichaelDeBoey MichaelDeBoey removed the needs-response We need a response from the original author about this issue/PR label Apr 26, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants