React 19 and Server Components

2025-04-13

⚛️ React 19 and Server Components

React 19 brings improved support for Server Components (RSC), and it's fully compatible with .mdx files rendered in Server Components. This integration allows for seamless inclusion of MDX content within your server-rendered pages.


🔄 Breaking Change in Next.js 15: Async Props

With the release of Next.js 15, there's a significant shift in how certain request-specific data is accessed. APIs such as params, searchParams, cookies, and headers are now asynchronous. This means they return Promises and must be awaited, even within Server Components.

❗ Why This Matters

Previously, in Next.js 14 and earlier, these APIs were synchronous. For example:

// Next.js 14
export default function Page({ params }: { params: { slug: string } }) {
  const slug = params.slug;
  return <div>Post: {slug}</div>;
}

In Next.js 15, attempting to access params synchronously will result in errors because params is now a Promise:

// ❌ This will cause an error in Next.js 15
export default function Page({ params }: { params: { slug: string } }) {
  const slug = params.slug; // Error: Cannot read property 'slug' of undefined
  return <div>Post: {slug}</div>;
}

✅ Correct Usage in Next.js 15

To adapt to this change, you should await the params object:

// Next.js 15
export default async function Page({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = await params;
  return <div>Post: {slug}</div>;
}

This pattern ensures that you're correctly handling the asynchronous nature of these APIs.


🧩 Key Patterns

When working with MDX content and custom components, it's essential to maintain consistent styling and structure. Here's how you can achieve that:

🖋️ Using prose for Layout

Wrap your MDX content within a styled <article> using Tailwind's prose class to ensure consistent typography:

<article className="prose dark:prose-invert max-w-3xl mx-auto py-10">
  <Content />
</article>

This setup provides a clean and readable layout for your content.

🧱 Customizing Components with useMDXComponents

To map custom components like <h1> or <Button>, use the useMDXComponents hook:

import type { MDXComponents } from "mdx/types";
import { Button } from "@/components/ui/button";

export function useMDXComponents(
  components: MDXComponents = {}
): MDXComponents {
  return {
    h1: (props) => <h1 className="text-6xl" {...props} />,
    Button: (props) => <Button {...props} />,
    ...components,
  };
}

This approach allows you to define consistent styling and behavior for your MDX components across your application.


🛠️ Migration Tips

To facilitate the transition to Next.js 15, consider the following:


By understanding and adapting to these changes, you can ensure that your application remains compatible with Next.js 15 and leverages the latest features and improvements.