How to use mantine UI with next 13
Asked Answered
C

2

11

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??

Centrist answered 5/11, 2022 at 15:13 Comment(2)
what do you mean by App directory here?Hagiocracy
It's the new way of doing things in nextjs 13 instead of using the pages directory you use the app directoryCentrist
O
28

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

Oversight answered 6/11, 2022 at 19:12 Comment(4)
@nicolasangela this approach worked perfectly for me, fwiw. Thank you!Felicefelicia
When using this code, I'm getting this error: error - SyntaxError: Unexpected token u in JSON at position 0 at JSON.parse (<anonymous>) Any ideas about why?Fate
@ErzaScarlet, i don't know why, but i convert RootStyleRegistry to arrow function instead of function, it worksMaggiemaggio
` "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; `Maggiemaggio
S
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.

Smythe answered 23/4, 2023 at 12:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.