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

[V5] Getting FOUC with default Remix template #1734

Closed
kwiat1990 opened this issue Jul 4, 2022 · 30 comments
Closed

[V5] Getting FOUC with default Remix template #1734

kwiat1990 opened this issue Jul 4, 2022 · 30 comments

Comments

@kwiat1990
Copy link

kwiat1990 commented Jul 4, 2022

What package has an issue

@mantine/core

Describe the bug

I'm getting FOUC using default Remix template with updated Remix, React and Mantine (5.0.0-alpha.19) packages. I've tried using npm and yarn as well. The issueis visible on intiial page load as well as on error/catch boundries.

A solution I'm currently using along with npm (remix-run/remix#1136 (comment)) doesn't work anymore due to changes in Mantine's Emotion cache. Therefore I have tried to implement caching based on this approach from Chakra UI: https://chakra-ui.com/getting-started/remix-guide#2-provider-setup. Sadly with no luck. The only difference is that I don't get errors in browser console due to mismatches in <head> but FOUC is still present.

The error I get using injectStylesIntoStaticMarkup:

react-dom.development.js:86 Warning: Expected server HTML to contain a matching <meta> in <head>.

In which browser did the problem occur

Chrome

If possible, please include a link to a codesandbox with the reproduced problem

No response

Do you know how to fix the issue

No

Are you willing to participate in fixing this issue and create a pull request with the fix

No response

Possible fix

No response

@kwiat1990 kwiat1990 added the bug label Jul 4, 2022
@johnsiras
Copy link

What package has an issue

@mantine/core

Describe the bug

I'm getting FOUC using default Remix template with updated Remix, React and Mantine (5.0.0-alpha.19) packages. I've tried using npm and yarn as well. The issueis visible on intiial page load as well as on error/catch boundries.

A solution I'm currently using along with npm (remix-run/remix#1136 (comment)) doesn't work anymore due to changes in Mantine's Emotion cache. Therefore I have tried to implement caching based on this approach from Chakra UI: https://chakra-ui.com/getting-started/remix-guide#2-provider-setup. Sadly with no luck. The only difference is that I don't get errors in browser console due to mismatches in <head> but FOUC is still present.

The error I get using injectStylesIntoStaticMarkup:

react-dom.development.js:86 Warning: Expected server HTML to contain a matching <meta> in <head>.

In which browser did the problem occur

Chrome

If possible, please include a link to a codesandbox with the reproduced problem

No response

Do you know how to fix the issue

No

Are you willing to participate in fixing this issue and create a pull request with the fix

No response

Possible fix

No response

Hello! I think this was a problem on emotion cache i've made a repository that interacts with the emotion cache
https://github.com/Johnsiras/remix-mantine-v5

@kwiat1990
Copy link
Author

kwiat1990 commented Jul 5, 2022

@johnsiras at the first sight the code in your repo doesn’t look different to what I had and in my case it didn’t work.

EDIT: I have tried your code out but I'm still getting FOUC:

@johnsiras
Copy link

@johnsiras at the first sight the code in your repo doesn’t look different to what I had and in my case it didn’t work.

EDIT: I have tried your code out but I'm still getting FOUC:

maybe try going upgrading down on some packages, cause i updated it all the packages to latest.

@kwiat1990
Copy link
Author

Well, I don't think that will be a solution, but I downgraded react to 17.0.2 and still got FOUC.

Btw. In your repo you should use some of Mantine components to see FOUC. I can see it with a simple button.

@rtivital
Copy link
Member

Fixed in 5.0

@hiql
Copy link

hiql commented Jul 26, 2022

Not fixed yet?
I tried the latest remix-mantine-template, and still have the problem.

@correiarmjoao
Copy link

I don't think this is an issue with mantine, had the same problem today and updated my repo to work with v5, I did not have enough time to fully understand what is going on but here are some of the things that I found.

import { RemixBrowser } from '@remix-run/react';
import { hydrate } from 'react-dom';
import { ClientProvider } from '@mantine/remix';

hydrate(
  <ClientProvider>
    <RemixBrowser />
  </ClientProvider>,
  document
);

Remix does not seem to be running the entry.client.tsx for error pages and because of that the ClientProvider cannot set the tags on the head. I worked around it by moving this step to a component inside the route.

// ~/app/components/Document.tsx
const clientStyleData = useContext(ClientStyleContext);
const mantineCache = useEmotionCache()

useEffect(() => {
  const cache = mantineCache
  cache.sheet.container = document.head;
  const tags = cache.sheet.tags;
  cache.sheet.flush();
  tags.forEach((tag) => {
    (cache.sheet as any)._insertTag(tag);
  });
  clientStyleData?.reset();
}, []);

This works and the tags are applied but the global styles for some reason are not. I think it is because the cache does not change so I created a context with a cacheProvider and different emotion cache that I recreate manually just to force the global styles to be added and it works.

I'll probably spend some more time on this in the weekend, maybe we don't need an additional emotion cache and can flag emotion to reapply the global styles using the mantine cache.

@rtivital
Copy link
Member

Thanks for the investigation @correiarmjoao, please share what you will be able to find

@kevinwolfcr
Copy link

As far as I've tested, this only happens with I have either a meta or links function exported from any route. Commenting them removes the FOUC and applies the global styles 🤔

@kevinwolfcr
Copy link

kevinwolfcr commented Aug 1, 2022

Update: I added a custom emotionCache as the docs says and it works, no warnings, hydration, or global styles issues.

Works with React 18 and Mantine 5.

@rtivital what would be the consequences of making createEmotionCache({ key: "mantine" }) the default value for the emotionCache prop in the MantineProvider?

@rtivital
Copy link
Member

rtivital commented Aug 1, 2022

It should be fine, could not think of any issues with that.
I've added createEmotionCache({ key: "mantine" }) to mantine-remix-template, but the issue is still there – does not seem to work.

@kevinwolfcr
Copy link

🤔 just cloned mantine-remix-template, added this and worked:

Screen Shot 2022-08-01 at 15 17 12

@jopesh
Copy link
Contributor

jopesh commented Aug 8, 2022

@elkevinwolf This works like a charm for me (Remix 1.6.7 and Mantine 5.1.0)!

@zemd
Copy link

zemd commented Aug 8, 2022

it works fine when I share cache between root.tsx, entry.client.tsx and entry.server.tsx, except 1 thing - Modal windows are broken: 1. their position is shifting, 2. page scroll is not working, 3. modal header styles are missing and close button also appears in wrong place.

when I eliminate emotion cache, modals work as expected but FOUC annoys.
tested with remix 1.6.5, 1.6.7, reactjs 17.0.2, 18.2.0, mantine 5.0.0, 5.0.2, 5.0.3, 5.1.0

p.s. this happens when your build targets production environment. dev env works fine

@zemd
Copy link

zemd commented Aug 8, 2022

replaced

hydrate(
   <ClientProvider emotionCache={cache}>
     <RemixBrowser />
   </ClientProvider>,
   document
);

with

hydrateRoot(document, <RemixBrowser />);

and this fixed all issues.

@viczam
Copy link

viczam commented Sep 1, 2022

@zemd can you please share a repo with a working example?

@zemd
Copy link

zemd commented Sep 1, 2022

@viczam sorry, but no. also the latest update broke styles again, and I had to switch back to react17 hydrate function, remove emotion cache and return <ClientProvider/>. there is definitely an issue with mantine-remix style integration, because next.js doesn't have the same issues.

@oncet
Copy link

oncet commented Sep 3, 2022

Fixed in 5.0

Using Mantine v5.2.4 and still getting the same error as OP plus a warning from React for using hydrate instead of hydrateRoot:

Warning: ReactDOM.hydrate is no longer supported in React 18. Use hydrateRoot instead. Until you switch to the new API, your app will behave as if it's running React 17.

But not perceiving any FOUC.

Tried switching to hydrateRoot method:

hydrateRoot(
  document,
  <ClientProvider>
    <RemixBrowser />
  </ClientProvider>
);

But this breaks other things and triggers several hydration warnings and errors:

Warning: Expected server HTML to contain a matching <meta> in <head>.
Error: Hydration failed because the initial UI does not match what was rendered on the server.
Warning: An error occurred during hydration. The server HTML was replaced with client content in <#document>.
Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.

This is the repository:

@dsschneidermann
Copy link

dsschneidermann commented Sep 3, 2022

This is the repository:

I believe that you need to have an explicit createEmotionCache({ key: "mantine" }) in your root.tsx render function, passing it to the MantineProvider. This should be with React 18 and hydrateRoot.

Edit: Just confirmed it with my own working solution.

Edit2: Possibly its just reacting to the different value of prepend, which is true by default. In Remix it has to match the placement of <StylesPlaceholder /> in your html head. Eg if you insert styles at the bottom, you need to hydrate with a "prepend: false" emotionCache.

@oncet
Copy link

oncet commented Sep 3, 2022

@dsschneidermann

Thank you so much. Adding createEmotionCache({ key: "mantine" }) to entry.client.tsx solved the problem, seems to be working like a charm.

Here is the complete file:

import { RemixBrowser } from "@remix-run/react";
import { hydrateRoot } from "react-dom/client";
import { ClientProvider } from "@mantine/remix";
import { createEmotionCache } from "@mantine/core";

createEmotionCache({ key: "mantine" });

hydrateRoot(
  document,
  <ClientProvider>
    <RemixBrowser />
  </ClientProvider>
);

Maybe Mantine docs should add this to their Remix guide.

@rtivital
Copy link
Member

rtivital commented Sep 3, 2022

I do not really know why it makes it work, need to test it out. Did it resolve your issue with React 18?

@dsschneidermann
Copy link

It seems the default of prepend: true for the emotionCache is no good for Remix, where you have to place the StylespPlaceholder in your html head yourself, and the styles are placed there during SSR. If you set prepend: false (or undefined), I'm guessing that emotion doesn't do any changes, and then it works for hydration.

It doesn't matter where you initialize the emotion cache eg. client entry or root or MantineProvider, and testing it earlier, I didn't need a ClientProvider either for everything to work. It's really a credit to Remix for having such good control over the html.

So the React 18 template is simpler than 17, but I'm not exactly an expert on what makes emotion tick in SSR/browser-side, so I can't yet PR the template repo. It just seems to have perfect compatibility with React 18 to me (portals/modals aside, possibly).

@rtivital
Copy link
Member

rtivital commented Sep 3, 2022

Okay, thanks @dsschneidermann, I'll wiggle things around and see whether we can fix it, prepend: true by default is a mistake, it should not be there, I'll remove that with next patch, then let's see how's it going from there.

@stephen776
Copy link

Can this be re-opened? I’m having this issue with latest template and have tried everything mentioned in this thread. Happy to help if I can provide more info.

I’m getting hydration errors in production but things work fine in development

@rtivital
Copy link
Member

@stephen776, please provide a repository with minimal reproduction, I do not see any issues in mantine-remix-template

@stephen776
Copy link

Please disregard. My issue was unrelated.

@alukach
Copy link

alukach commented Oct 21, 2022

@rtivital For a repository with minimal reproduction, please see: https://github.com/alukach/mantine-remix-rendering-issue

Description can be found here: mantinedev/remix-template#4

@richardanewman
Copy link

I only experience FOUC with devtools open in firefox. If it's closed, FOUC goes away. In chorme, the font is a little jumpy with dev tools open but no flash. Nothing with devtools closed.

@meznaric
Copy link

It's finally working for me. Here is what I did:

  1. Extract createEmotionCache({ key: "mantine" }); into some utility file and call it emotionCache
  2. Update entry.client.ts
-  <ClientProvider>
+  <ClientProvider emotionCache={emotionCache}>
  1. Update entry.server.ts
- const server = createStylesServer();
+ const server = createStylesServer(emotionCache);
  1. Update root.ts
```tsx
    <MantineProvider
+     emotionCache={emotionCache}
      theme={theme}

It works now 🎉

@richardanewman I assume you don't see it with dev tools because all assets are cached and your (JS) load happens instantaneously and consequently adding client side stylesheets as well.

@nastynaz
Copy link

Thank you! This was such a pain to fix. I also had the issue of Mantine not playing well with Cloudflare Pages.

I wrote up a guide so that others don't need to go through the pain: how to make remix work with mantine and cloudflare pages.

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