Next.js combined with a UI framework like MUI or Chakra-ui is a pretty awesome combination. It’s really fast to build something that looks polished and provides a good user experience. Then, combine Vercel for hosting, and deployment is nearly instant. I do this often to test value props before wasting time on an idea that no one wants. Next 13 introduced a new next app folder that adds significant features while making some things a little more complex.
Next 13 /app folder
I attended the Next virtual conference in Oct 2022. There were a few major announcements, including the new /app folder which is an alternative to the /pages folder. The new /app folder provides these significant improvements over /pages:
- All components are React Server Components by default
- Built-in error handling using React Error Boundaries
- Built-in loading state handling using React Suspense
- File naming conventions allow non-routing components to live in the same folder
I won’t go into how all of this works in this post. There is a really great session from the conference here that illustrates how these work along with the new “use” React hook for much simpler data fetching.
Keep in mind that as of Nov 2022 the /app folder is still considered in beta. The /pages folder is still the default way to handle page routing.
React Server Components
A key change with the /app folder structure is that all components are react server components by default. A react server component renders on the server and only delivers the minimal amount of HTML, CSS and JavaScript to the client. In the case of static components there might not be any JavaScript delivered at all. This provides a potential performance boost to apps in the browser by offloading work to the server. Much of that work can also be done at build time.
The downside of react server components is that it introduces some complexity to building components. This is because the server rendering environment is different than the browser. For example, the server has no context provider. Any components rendered on the server that attempt to access context will cause an error. Fortunately, there’s a way around this by specifying an individual component should render on the client by adding…
'use client'
Code language: JavaScript (javascript)
… to the top of the component.
This allows you to alternate between server and client components fairly seamlessly. The Next 13 beta documentation has a good table that summarizes when to use server and client components.
Using Chakra-UI components with the next app folder
I tested Chakra-ui with the Next app folder and found that it was possible to use a combination of server and client components. According to the Next docs, any combination of server and client components is possible. The Next docs have a good explanation of how client and server rendering work together.
You should choose the right type of component based on several key factors. Here is an easy way to understand when to use each.
Server Component
For components that fetch data, use sensitive keys or render to static HTML
Client Component
For components that users interact with, use state or require browser-specific functions
For Chakra-ui, this means that the root layout component that adds the <ChakraProvider> has to be a client component since it uses react context. Other components that render to static html like <Flex> and <Box> can be used in server components.
Next app folder Root Layout example
Notice the ‘use client’ directive at the top of the file.
'use client'
import Nav from './nav'
import { ChakraProvider } from '@chakra-ui/react'
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang='en'>
<head>
<title>Create Next App</title>
<meta name='description' content='Generated by create next app' />
<link rel='icon' href='/favicon.ico' />
</head>
<ChakraProvider>
<body>
<header>
<Nav />
<hr />
</header>
{children}
</body>
</ChakraProvider>
</html>
)
}
Code language: JavaScript (javascript)
Next app folder Server Component example
Because the following code doesn’t include the ‘use client’ directive, it will be rendered as a server component.
import Link from 'next/link'
import { HStack } from '@chakra-ui/react'
export default function Nav() {
return (
<HStack>
<Link href='/'>Home</Link>
<Link href='/blog'>Blog</Link>
</HStack>
)
}
Code language: JavaScript (javascript)
Most testing ahead
I haven’t yet tested all the Chakra-ui components to know whether they will all work in the Next app folder. I suspect that all display components will work fine as client components, as they do in the /pages folder. I’ll update this post if I discover anything that doesn’t work.
The Next app folder requires a new way of thinking
The introduction of React server components and the Next app folder will change the way we think about structuring components. The ideal goal is to let the server pre-render as much as possible and to leave the least rendering for the browser. In a way, it’s similar to a server-rendered framework like PHP where you have to decide which app logic belongs in PHP and which in JavaScript. Are we moving backwards? Maybe. But there’s certainly nothing wrong with improving the experience for users.