router icon indicating copy to clipboard operation
router copied to clipboard

Flash of unstyled content with Mantine & mismatched initial UI

Open kennyjwilli opened this issue 1 year ago • 1 comments

Which project does this relate to?

Start

Describe the bug

I am working on a project using the Mantine component library and am trying out Start. I have set up the basic Start configuration and a basic configuration of Mantine. When I visit the app URL in the browser, the app loads, but there are two problems.

  1. There is a brief flash of unstyled content.
  2. There is a warning message that "Hydration failed because the initial UI does not match what was rendered on the server." It also informs me that "Warning: Expected server HTML to contain a matching

I have included the full stacktraces below.

Warning: Expected server HTML to contain a matching

@mantine_core.js?v=e7ecb175:3546 Warning: Expected server HTML to contain a matching <script> in <div>.
    at script
    at ColorSchemeScript (http://localhost:3000/_build/node_modules/.vinxi/cache/client/deps/@mantine_core.js?v=e7ecb175:4157:3)
    at Head (http://localhost:3000/_build/node_modules/.vinxi/cache/client/deps/@tanstack_start.js?v=e7ecb175:558:3)
    at Html (http://localhost:3000/_build/node_modules/.vinxi/cache/client/deps/@tanstack_start.js?v=e7ecb175:544:3)
    at RootDocument (http://localhost:3000/_build/app/routes/__root.tsx?t=1729351401814:54:25)
    at RootComponent
    at MatchInnerImpl (http://localhost:3000/_build/node_modules/.vinxi/cache/client/deps/chunk-AOWOSOBF.js?v=e7ecb175:3567:3)
    at SafeFragment (http://localhost:3000/_build/node_modules/.vinxi/cache/client/deps/chunk-AOWOSOBF.js?v=e7ecb175:3487:87)
    at SafeFragment (http://localhost:3000/_build/node_modules/.vinxi/cache/client/deps/chunk-AOWOSOBF.js?v=e7ecb175:3487:87)
    at SafeFragment (http://localhost:3000/_build/node_modules/.vinxi/cache/client/deps/chunk-AOWOSOBF.js?v=e7ecb175:3487:87)
    at MatchImpl (http://localhost:3000/_build/node_modules/.vinxi/cache/client/deps/chunk-AOWOSOBF.js?v=e7ecb175:3510:3)
    at CatchBoundaryImpl (http://localhost:3000/_build/node_modules/.vinxi/cache/client/deps/chunk-AOWOSOBF.js?v=e7ecb175:1242:5)
    at CatchBoundary (http://localhost:3000/_build/node_modules/.vinxi/cache/client/deps/chunk-AOWOSOBF.js?v=e7ecb175:1222:32)
    at MatchesInner (http://localhost:3000/_build/node_modules/.vinxi/cache/client/deps/chunk-AOWOSOBF.js?v=e7ecb175:4147:19)
    at SafeFragment (http://localhost:3000/_build/node_modules/.vinxi/cache/client/deps/chunk-AOWOSOBF.js?v=e7ecb175:3487:87)
    at Matches (http://localhost:3000/_build/node_modules/.vinxi/cache/client/deps/chunk-AOWOSOBF.js?v=e7ecb175:4137:18)
    at RouterContextProvider (http://localhost:3000/_build/node_modules/.vinxi/cache/client/deps/chunk-AOWOSOBF.js?v=e7ecb175:4233:3)
    at RouterProvider (http://localhost:3000/_build/node_modules/.vinxi/cache/client/deps/chunk-AOWOSOBF.js?v=e7ecb175:4252:27)
    at StartClient (http://localhost:3000/_build/node_modules/.vinxi/cache/client/deps/@tanstack_start.js?v=e7ecb175:713:14)
Hydration failed because the initial UI does not match what was rendered on the server.

Uncaught Error: Hydration failed because the initial UI does not match what was rendered on the server.
    at throwOnHydrationMismatch (chunk-WMXHI54R.js?v=e7ecb175:9471:17)
    at tryToClaimNextHydratableInstance (chunk-WMXHI54R.js?v=e7ecb175:9492:15)
    at updateHostComponent (chunk-WMXHI54R.js?v=e7ecb175:14792:13)
    at beginWork (chunk-WMXHI54R.js?v=e7ecb175:15933:22)
    at HTMLUnknownElement.callCallback2 (chunk-WMXHI54R.js?v=e7ecb175:3672:22)
    at Object.invokeGuardedCallbackDev (chunk-WMXHI54R.js?v=e7ecb175:3697:24)
    at invokeGuardedCallback (chunk-WMXHI54R.js?v=e7ecb175:3731:39)
    at beginWork$1 (chunk-WMXHI54R.js?v=e7ecb175:19763:15)
    at performUnitOfWork (chunk-WMXHI54R.js?v=e7ecb175:19196:20)
    at workLoopSync (chunk-WMXHI54R.js?v=e7ecb175:19135:13)

Followed by this message, no stacktrace.

Warning: An error occurred during hydration. The server HTML was replaced with client content in <div>.
There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.

Uncaught Error: There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.
    at updateHostRoot (chunk-WMXHI54R.js?v=e7ecb175:14758:65)
    at beginWork (chunk-WMXHI54R.js?v=e7ecb175:15931:22)
    at beginWork$1 (chunk-WMXHI54R.js?v=e7ecb175:19751:22)
    at performUnitOfWork (chunk-WMXHI54R.js?v=e7ecb175:19196:20)
    at workLoopSync (chunk-WMXHI54R.js?v=e7ecb175:19135:13)
    at renderRootSync (chunk-WMXHI54R.js?v=e7ecb175:19114:15)
    at recoverFromConcurrentError (chunk-WMXHI54R.js?v=e7ecb175:18734:28)
    at performConcurrentWorkOnRoot (chunk-WMXHI54R.js?v=e7ecb175:18682:30)
    at workLoop (chunk-WMXHI54R.js?v=e7ecb175:195:42)
    at flushWork (chunk-WMXHI54R.js?v=e7ecb175:174:22)

Your Example Website or App

https://stackblitz.com/edit/vitejs-vite-ig3cnf

Steps to Reproduce the Bug or Issue

I have tried to repro on Stackblitz, but I'm not sure that it supports Start. The repro is really quite simple though.

I have pushed a repro here: https://github.com/kennyjwilli/start-mantine-fouc.

  1. pnpm i
  2. pnpm run dev
  3. Visit http://localhost:3000 and observe the flash of unstyled content.

Expected behavior

As a user, I expect the content to be rendered with the correct initial styling, not flashing any unstyled content. I also expect no warnings in the browser console.

Screenshots or Videos

https://github.com/user-attachments/assets/afa5517b-b5b2-42ac-9344-fa1e95a688aa

Platform

  • OS: MacOS 14.6.1
  • Browser: Chrome
  • Version: 128.0.6613.138

Additional context

A key component to setting up Mantine with SSR is to add the ColorSchemeScript component to the head of the application (docs). In my example, I have done just that. Since I am using Start, the head of the app uses Head and looks like this:

<Head>
  <ColorSchemeScript/>
  <Meta/>
</Head>

If I comment out ColorSchemeScript, the console warnings go away, but the flash of unstyled content remains.

kennyjwilli avatar Oct 19 '24 15:10 kennyjwilli

I think they want you to link css files like this in loader:

import mantineCssUrl from '@mantine/core/styles.css?url'

//...

  links: () => [{ rel: 'stylesheet', href: mantineCssUrl }]

As in example:

https://github.com/TanStack/router/blob/main/examples/react/start-trellaux/app/routes/__root.tsx#L17,L39

ViliamKopecky avatar Oct 20 '24 15:10 ViliamKopecky

This worked for me! Thanks!

drew-dulgar avatar Oct 22 '24 11:10 drew-dulgar

@drew-dulgar I'm running into the same as mentioned in #1917. I believe the ColorSchemeScript is necessary when using SSR since it's setting the data-mantine-color-scheme attribute based on the scheme in local storage. I'm hopeful this can be resolved in Start so that scripts can be added to the head when necessary in cases like this and not duplicated in the root div.

corydeppen avatar Oct 23 '24 20:10 corydeppen

I think they want you to link css files like this in loader:

import mantineCssUrl from '@mantine/core/styles.css?url'

//...

links: () => [{ rel: 'stylesheet', href: mantineCssUrl }] As in example:

https://github.com/TanStack/router/blob/main/examples/react/start-trellaux/app/routes/__root.tsx#L17,L39

I didn't realize the ?url was needed in the import, that fixed it for me. Thanks!

davidchalifoux avatar Nov 21 '24 01:11 davidchalifoux

can this be closed?

schiller-manuel avatar Mar 04 '25 14:03 schiller-manuel

@schiller-manuel

can this be closed?

Yes and no... Please keep in mind that Mantine applications are usually styled with CSS modules, so issues are still going to pop up until https://github.com/TanStack/router/issues/3023 is fixed...

@kennyjwilli - remeber to also spread the mantineHtmlProps on the <html> tag to avoid additional hydration errors:

import { mantineHtmlProps } from '@mantine/core';

// ...

<html lang="en" {...mantineHtmlProps}>
  {/* ... */}
</html>

icflorescu avatar Mar 07 '25 22:03 icflorescu

This setup for mantine with tanstack start, colorscheme without flashing or hydration errors you need to setup a client side component for colorScheme toggler

and in app.config add this to vite

	vite: {
		ssr: {
			noExternal: ["@mantine/*"],
		},

import { DefaultCatchBoundary } from "@/components/DefaultCatchBoundary"
import { NotFound } from "@/components/NotFound"
import { seo } from "@/utils/seo"
import {
	HeadContent,
	Outlet,
	Scripts,
	createRootRoute,
} from "@tanstack/react-router"
import { TanStackRouterDevtools } from "@tanstack/react-router-devtools"
import * as React from "react"
import {
	mantineHtmlProps,
	ColorSchemeScript,
	MantineProvider,
} from "@mantine/core"

import appCss from "@/styles/app.css?url"
import mantineCssUrl from "@mantine/core/styles.css?url"

export const Route = createRootRoute({
	head: () => ({
		meta: [
			{
				charSet: "utf-8",
			},
			{
				name: "viewport",
				content: "width=device-width, initial-scale=1",
			},
			...seo({
				title:
					"TanStack Start | Type-Safe, Client-First, Full-Stack React Framework",
				description: `TanStack Start is a type-safe, client-first, full-stack React framework. `,
			}),
		],
		links: [
			{ rel: "stylesheet", href: appCss },
			{ rel: "stylesheet", href: mantineCssUrl },
			{
				rel: "stylesheet",
				href: "https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;700&display=swap",
			},
			{
				rel: "apple-touch-icon",
				sizes: "180x180",
				href: "/apple-touch-icon.png",
			},
			{
				rel: "icon",
				type: "image/png",
				sizes: "32x32",
				href: "/favicon-32x32.png",
			},
			{
				rel: "icon",
				type: "image/png",
				sizes: "16x16",
				href: "/favicon-16x16.png",
			},
			{ rel: "manifest", href: "/site.webmanifest", color: "#fffff" },
			{ rel: "icon", href: "/favicon.ico" },
		],
	}),
	errorComponent: (props) => {
		return (
			<RootDocument>
				<DefaultCatchBoundary {...props} />
			</RootDocument>
		)
	},
	notFoundComponent: () => <NotFound />,
	component: RootComponent,
})

function RootComponent() {
	return (
		
			<RootDocument>
				<Outlet />
			</RootDocument>
	)
}

function RootDocument({ children }: { children: React.ReactNode }) {
	return (
		<html lang="en" {...mantineHtmlProps}>
			<head>
				<script
					crossOrigin="anonymous"
					src="//unpkg.com/react-scan/dist/auto.global.js"
				/>
				<ColorSchemeScript defaultColorScheme="dark" />
				<HeadContent />
			</head>
			<body>
                               <MantineProvider withGlobalClasses={false} defaultColorScheme="dark">
				{children}
	                 	</MantineProvider>
				<TanStackRouterDevtools position="bottom-right" />
				<Scripts />
			</body>
		</html>
	)
}

mapsgeek avatar Apr 16 '25 23:04 mapsgeek

I have the same issue. I tried all examples but still have the FOUC.

Tsouef avatar Apr 26 '25 21:04 Tsouef

I was in the process of moving a small project from React Router (where everything runs fine) to Tanstack and I ran into this very quickly. Show stopper! 😟

dperetti avatar Sep 01 '25 16:09 dperetti

believe the same issue is happening when using next themes

ElasticBottle avatar Sep 09 '25 13:09 ElasticBottle

updates on React Router (Vite) + mantine?

Pyakz avatar Oct 04 '25 15:10 Pyakz

same issue here with NextUI and next-themes.

0x0501 avatar Nov 02 '25 06:11 0x0501