10

I was trying to use mantine UI with NextJS 13 using the app directory, I have to wrap everything in the MantineProvider component but I don't know where to put it.

I tried this

layout.js

/* eslint-disable @next/next/no-head-element */
import { MantineProvider } from '@mantine/core';
export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <MantineProvider
    withGlobalStyles
    withNormalizeCSS
    theme={{
      /** Put your mantine theme override here */
      colorScheme: 'dark',
    }}>
      <html>
        <head></head>
        <body>{children}</body>
      </html>
    </MantineProvider>
    
  );
}

and it didn't work so, is there any solution??

zhulien
  • 5,145
  • 3
  • 22
  • 36
Youssef-mic
  • 123
  • 1
  • 8

2 Answers2

27

So I've been interested in solving this problem too.

Step 1 is moving third-party providers to a "client-only" component. See here

The next step is to follow this thread on mantine's github, while they work out compatibility issues with emotion & next13

Lastly, this seems to be the only official implementation example on Mantine's github using Mantine with the new Next.js app directory. Here's how they approached it:

/app/emotion.tsx

"use client";
import { CacheProvider } from "@emotion/react";
import { useEmotionCache, MantineProvider } from "@mantine/core";
import { useServerInsertedHTML } from "next/navigation";

export default function RootStyleRegistry({
  children
}: {
  children: React.ReactNode
}) {
  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 withGlobalStyles withNormalizeCSS>
        {children}
      </MantineProvider>
    </CacheProvider>
  )
}

/app/layout.tsx

import RootStyleRegistry from './emotion';

export default function RootLayout({ children }) {
  return (
   <html lang="en-US">
     <head />
     <body>
       <RootStyleRegistry>{children}</RootStyleRegistry>
     </body>
   </html>
  );
}

Hope this helps. Let me know if you get it working

nicolasangelo
  • 291
  • 1
  • 3
  • @nicolasangela this approach worked perfectly for me, fwiw. Thank you! – Brooklyn Nicholson Nov 15 '22 at 20:20
  • When using this code, I'm getting this error: `error - SyntaxError: Unexpected token u in JSON at position 0 at JSON.parse ()` Any ideas about why? – Manpreet Apr 17 '23 at 10:04
  • @ErzaScarlet, i don't know why, but i convert RootStyleRegistry to arrow function instead of function, it works – Trọng Nguyễn Công Apr 21 '23 at 04:16
  • ` "use client"; import { CacheProvider } from "@emotion/react"; import { useEmotionCache, MantineProvider } from "@mantine/core"; import { useServerInsertedHTML } from "next/navigation"; const RootStyleRegistry = ({ children }: { children: React.ReactNode }) => { .... ); }; export default RootStyleRegistry; ` – Trọng Nguyễn Công Apr 21 '23 at 04:17
2

I faced issues with this combo too (running Mantine 6.0.x + NextJS 13 with appDir enabled). My mistake was that I was enclosing next-auth's SessionProvider within the providers.tsx, and as the topmost item. This messed up the styles loading and mantine styles were not loading till a route change.

Here is the sample code that works for me:

providers.tsx

"use client";
...
...
return (
        <ColorSchemeProvider ...>
            <MantineProvider withGlobalStyles withNormalizeCSS ...>
                <ModalsProvider>
                    <SpotlightProvider ...>
                        {children}
                    </SpotlightProvider>
                </ModalsProvider>
                {/* Notifications system */}
                <Notifications .../>
            </MantineProvider>
        </ColorSchemeProvider>
    );

and in the root layout.tsx

const RootLayout = ( {children,}: {children: ReactNode} ) => {
    return (
        <html lang="en">
            <body>
            <SessionProvider>
                <Providers>
                    {children}
                </Providers>
            </SessionProvider>
            </body>
        </html>
    )
}

PS: I also faced Error - SyntaxError: Unexpected token u in JSON at position 0 at JSON.parse ... that Erza Scarlet mentioned in the previous answer's comment. To fix it, I migrated all my export default function Fn() to default var exports (consts with arrow fns) and also updated React, NextJs and Mantine to the latest versions. That fixed it.

Deepak Thomas
  • 3,355
  • 4
  • 37
  • 39