-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Mantine with Next.js 13 app dir #2815
Comments
|
@rtivital Are you planning on supporting Next 13's app folder in the future? |
Yes, it is planned, but it depends on emotion, there are several opened issues that you can track: |
I got it working based on this issue (emotion-js/emotion#2928) – https://github.com/mantinedev/mantine-next-template/tree/next-13-app/app |
somehow, the above fix works for |
All Mantine components can be used only if |
They default to server components but u can add |
Hi, thanks for the amazing project! Are there any plans to make Mantine compatible with server components? |
No, server components cannot have state/context/refs, it is not possible to build components without these things. Currently, it is not planned to add |
Seems like this is technically a Next issue for which they have documentation (beta): https://beta.nextjs.org/docs/rendering/server-and-client-components#rendering-third-party-context-providers-in-server-components. Whereas third-party maintainers can add the |
@johnhenry actually this is a react issue: On the latest RFC: they decided on |
I am having this problem
When I upgrade to nextjs 13, any idea how I can fix this? |
Thanks for all of this. I'm a bit confused; I have been able to successfully use Mantine components in NextJS 13 without the |
This worked for me until I deployed to Vercel, then I got a blank white page. I managed to fix that using suggestions from emotion-js/emotion#2928 but got flickering issues where the CSS wasn't loaded until a moment after the DOM. Here is the modified version of @rtivital's code that solved everything for me: 'use client'
import { CacheProvider } from '@emotion/react'
import { ColorScheme, ColorSchemeProvider, createEmotionCache, MantineProvider } from '@mantine/core'
import { useLocalStorage } from '@mantine/hooks'
import { useServerInsertedHTML } from 'next/navigation'
// must be created outside of the component to persist across renders
const cache = createEmotionCache({ key: 'my' })
cache.compat = true
export default function RootStyleRegistry({ children }: { children: JSX.Element }) {
useServerInsertedHTML(() => (
<style
data-emotion={`${cache.key} ${Object.keys(cache.inserted).join(' ')}`}
dangerouslySetInnerHTML={{
__html: Object.values(cache.inserted).join(' '),
}}
/>
))
return (
<CacheProvider value={cache}>
<MantineProvider
withGlobalStyles
withNormalizeCSS
emotionCache={cache}
>
{children}
</MantineProvider>
</CacheProvider>
)
} |
@rtivital I also tried this code, and confirmed that it works on pre-rendering(SSR/SG) correctly. If it doesn't bother you, I'll try to make PR. |
It is not ready for production based on issue in emotion repo, I've implemented a POC. I'll update the template once app dir is out of beta and emotion provides documentation. |
The version from @rtivital here from this repo seems to work fine for me but I'll see if I run into more problems. |
This comment was marked as off-topic.
This comment was marked as off-topic.
@Depechie Your issue is not related to app dir |
I tried the I ended up turning that off but if anyone found a way to drop the dark/light mode provider, please share. |
I've got this running in my own repo, but I'm still experiencing dramatic layout shifts on the first load of the website. From any page, doing Before, Mantine docs had a |
After searching through numerous cases I'd like to share my "current" workaround for Next.js 13 + Mantine + Emotion setup. It seems like working without FOUC/layout shifting for my minimal POC but this might break in certain cases. Please do share your experiences. Also I've extracted out critical logic into a single hook. You can merge the extracted hook into the 'emotion.tsx' if that's your jam. // 1. /app/layout.tsx
// use relative imports if you have to
import EmotionProvider from '$/components/Providers/emotion';
export default function RootLayout({ children }: { children: JSX.Element }) {
return (
<html>
<head></head>
<body>
<EmotionProvider>
{children}
</EmotionProvider>
</body>
</html>
);
}
// since layout.tsx & page.tsx is a Server Component you can do...
// const metadata : MetaData = { title: 'Awesome Mantine' }; jazz as you wish
// 2. /components/Providers/emotion.tsx
'use client';
import { useGluedEmotionCache } from '$/lib/emotionNextjsGlue';
import { CacheProvider } from '@emotion/react';
import { MantineProvider } from '@mantine/core';
export default function EmotionProvider({ children }: { children: JSX.Element }) {
const cache = useGluedEmotionCache();
return (
<CacheProvider value={cache}>
{/* You can wrap ColorSchemeProvider right here but skipping that for brevity ;) */}
<MantineProvider withGlobalStyles withNormalizeCSS emotionCache={cache}>
{children}
</MantineProvider>
</CacheProvider>
);
}
// 3. /lib/emotionNextjsGlue.tsx
import createCache from '@emotion/cache';
import { useServerInsertedHTML } from 'next/navigation';
import { useState } from 'react';
export const useGluedEmotionCache = (key = 'emotion') => {
const [cache] = useState(() => {
const cache = createCache({ key });
cache.compat = true;
return cache;
});
useServerInsertedHTML(() => {
const entries = Object.entries(cache.inserted);
if (entries.length === 0) return null;
const names = entries
.map(([n]) => n)
.filter((n) => typeof n === 'string')
.join(' ');
const styles = entries.map(([, s]) => s).join('\n');
const emotionKey = `${key} ${names}`;
return <style data-emotion={emotionKey} dangerouslySetInnerHTML={{ __html: styles }} />;
});
return cache;
}; I don't use css= Edit: simplified hook a bit |
Hello, please when will mantine ui support next app dir? I've been trying to get it to work to no avail, help? |
U can use it with mantine 7 instead of css module |
Thanks. I'll try it. |
|
I am wondering what should be the cause as Nextjs is allowing the workaround for it. Is it breaking anything? |
Sure. The components can be used in SSR without ```
|
So I wasn't sure if this should be in this discussion or in a different issue, but it's more of a question. |
@YechiamTK Probably should be a discussion but, yes, you can. Create a component with the AppShell (with the 'use client' directive) that accepts the { children } prop and wrap your RootLayout with it: // MainAppShell.tsx
'use client'
// ...
export default function MainAppShell({
children,
}: {
children: React.ReactNode;
}) {
const [opened, setOpened] = useState(false);
return (
<AppShell
header={<AppHeader />}
navbar={<AppNavbar opened={opened} setOpened={setOpened} />}
footer={<AppFooter />}
>
{children}
</AppShell>
);
} // layout.tsx
// ...
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang='en-US' dir='ltr'>
<body className={`${inter.className}`}>
<MainAppShell>{children}</MainAppShell>
</body>
</html>
);
} |
Is it possible to update this using mui example on injection. With this example some styles are duplicated |
@masterbater here is my basic app router set-up (with server inserted cache): export const myCache = createEmotionCache({ key: 'mantine' });
//...
const cache = useEmotionCache();
cache.compat = true;
//...
useServerInsertedHTML(() => (
<style
data-emotion={`${cache.key} ${Object.keys(cache.inserted).join(' ')}`}
dangerouslySetInnerHTML={{
__html: Object.values(cache.inserted).join(' '),
}}
/>
));
return (
<CacheProvider value={cache}>
<MantineProvider emotionCache={myCache} withGlobalStyles>
{children}
</MantineProvider>
</CacheProvider>
) |
I have that bro, issue is some styles I setup in component got overriden by the default styling of mantine. There might be some order issue with the existing example provided. So I use mui style and it fixes all the issue |
@masterbater ah, I see. Thought maybe you were missing the mantine cache key |
Reusing mantine cache or creating new one same issue. but anyway i have already complete integration from rtl to switch theme without any issue now, no FOUC |
Pease check the next 13 doc |
Am i just missing or has anybody notice that the css classes inserted twice, either in development or production? Just stumble upon the issue from here. Just add some extra checking to reduce the page size. cmiiw. 'use client';
import { CacheProvider } from '@emotion/react';
import { createEmotionCache, MantineProvider } from '@mantine/core';
import { useServerInsertedHTML } from 'next/navigation';
import { useRef } from 'react';
// must be created outside of the component to persist across renders
const cache = createEmotionCache({ key: 'my' });
cache.compat = true;
export default function RootStyleRegistry({
children,
}: {
children: JSX.Element;
}) {
const isServerInserted = useRef(false);
useServerInsertedHTML(() => {
if (!isServerInserted.current) {
isServerInserted.current = true;
return (
<style
data-emotion={`${cache.key} ${Object.keys(cache.inserted).join(' ')}`}
dangerouslySetInnerHTML={{
__html: Object.values(cache.inserted).join(' '),
}}
/>
);
}
});
return (
<CacheProvider value={cache}>
<MantineProvider withGlobalStyles withNormalizeCSS emotionCache={cache}>
{children}
</MantineProvider>
</CacheProvider>
);
} |
This works great, but does anyone have an example of how to do this implementing toggleColorScheme or some way to let user toggle the color scheme? Before App dir I used The workarounds so far are great, but none of them mention how to handle a changeable color scheme that I can find. |
Maybe we can do this in the way that the Redux Provider is used in the separate file as client component and used in the root layout |
try this, it work for me @Jared-Dahlke export default function RootStyleRegistry({
children,
}: {
children: React.ReactNode;
}) {
const cache = useEmotionCache();
cache.compat = true;
const [colorScheme, setColorScheme] = useLocalStorage<ColorScheme>({
key: "mantine-color-scheme",
defaultValue: "light",
getInitialValueInEffect: true,
});
useHotkeys([["mod+J", () => toggleColorScheme()]]);
const toggleColorScheme = (value?: ColorScheme) => {
// console.log("RootStyleRegistry value", colorScheme);
setColorScheme(value || (colorScheme === "dark" ? "light" : "dark"));
document.body.style.background =
colorScheme === "dark"
? "var(--mantine-color-white)"
: "var(--mantine-color-dark-7)";
document.body.style.color =
colorScheme === "dark"
? "var(--mantine-color-black)"
: "var(--mantine-color-dark-0)";
};
useServerInsertedHTML(() => (
<style
data-emotion={`${cache.key} ${Object.keys(cache.inserted).join(" ")}`}
dangerouslySetInnerHTML={{
__html: Object.values(cache.inserted).join(" "),
}}
/>
));
return (
<CacheProvider value={cache}>
<ColorSchemeProvider
colorScheme={colorScheme}
toggleColorScheme={toggleColorScheme}
>
<MantineProvider
theme={{ colorScheme }}
withGlobalStyles
withNormalizeCSS
withCSSVariables
>
{children}
</MantineProvider>
</ColorSchemeProvider>
</CacheProvider>
);
} |
Can we presume this as fixed now in 7.0? @rtivital |
We pray |
I can confirm this is fixed in Mantine v7! |
The issue is resolved in 7.0. Now you can use Mantine with Next.js app router without any additional setup. You can find templates and additional information on the Next.js guide page – https://mantine.dev/guides/next Thanks everyone for the feedback on this issue! |
What package has an issue
@mantine/core
Describe the bug
I use mantine dev as regular basis with next12. But when i put MantinProvider in app/pages.tsx or app/layout.tsx forlder. The app doesnt seems too work. Where to put __app.tsx requirements? sorry for bad english.
What version of @mantine/hooks page do you have in package.json?
"@mantine/hooks": "^5.6.2",
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
Possible fix
Server Component support
The text was updated successfully, but these errors were encountered: