Why Doesn't Material-UI or Chakra Work In The App Router?
Question: Why don't Material-UI or Chakra components work in the App Router?
Answer: It's a huge bummer that excellent component libraries like Material-UI and Chakra don't work with the NextJS App Router. Or do they? Well, that's the first point. They actually do work if the component that references the Material-UI or Chakra component are client components. And client compenents, despite their name, render on both the client and the server. They don't work with React Server Components (RSCs).
Client components are what we had with the Pages Router in the original version of NextJS. RSCs are now the default with the App Router. So effectively, if you want to turn your App Router application into a Pages Router application just turn all of your components into client components and you'll be able to use these libraries.
The reason why these libraries don't work is that they rely in a CSS-in-JS solution (specifically the very popular emotion library) to do their CSS. Emotion supports context based theming of components. In fact, even if you don't specify your own theme, you are still using theming when you use emotion, you are just using the stock theme.
To get the theme effeciently around the React tree without prop drilling emotion uses context to pass around the theme. React server components can't use context. But that's not really the problem. The problem is that when an RSC references a Material-UI button (as an example) the MUI component isn't marked as a client component but it still uses context. NextJS thinks that means the MUI button is a React Server Component, but it's using context, so boom goes the dynamite because RSCs can't use context.
The most straightforward way around this is to simply use a mix of React Server Components to get the data you need for rendering, then to pass that data to client components that use the component libaries. This is basically replicating the getServerSideProps
model we had with the Pages Router. Again, client components render on both the client and the server, so you aren't going to have any Server Side Rendering issues using this approach.
Another possible option is to wrap the MUI components in your own components that are marked as client components.
The roughest, but possibly the best long term option, would be to rethink your CSS styling/component strategy altogether and use either CSS modules, or Tailwind, in combination with a headless UI libraries give you components that work with either RSCs or client components.
It is worth noting that you can run pages
and app
directories side-by-side and convert routes one-by-one until your application is completely converted. You don't nee to lift and shift all the routes at once.