# Migrating to Next.js Server Components Layouts

> A simple guide to migrating your _app.tsx component to the new Server Components released with Next.js 13

*Published: 2022-10-27*
*Canonical: https://makerkit.dev/blog/tutorials/migrating-nextjs-layouts*

---

Vercel has finally shipped Next.js 13, and with it one of the most requested
features: nested **Layouts** using the new React 18 Server Components,
powered by React Suspense.

The changes and possibilities Next.js 13 brings are revolutionary:
thanks to the new Server Components and seamless Suspense integration, **Next.
js applications will be smaller and faster**.

With that said, transitioning from the good old `_app.tsx` root component to
Server Components won't be the simplest: the new Next.js 13 Layouts are
basically a whole new framework.

This blog post is ideal for those who are unsure how to migrate their apps
from the old `_app.tsx` to using the new Layouts Server Components.

## Bye Bye _app.tsx and _document.tsx

So, are we deleting `_app.tsx` and `_document.tsx`? Yes. These are no longer
needed when working with the new Next.js `app` directory. Gone. Done. Ciao.

This introduces lots of questions:

1. How do we pass data to a component?
2. How do we initialize our applications?
3. Where do we place our app-wide Providers?

Believe me, I was as confused as you are, and still am while writing this.
But let's go on.

The general rule that seems to be pushed by the Next.js team is: **fetch the
data in every component that needs it**, and use the provided utilities to
ensure dedupe and avoid multiple calls.

While requests made with `fetch` are automatically deduped and cached, it's not
the same when using different data-fetching utilities: for example, ORMs,
Firestore, and so on. In that case, we're going to use the React.js `cache`
utility.

## Initializing the application's state

The old `_app.tsx` was handy when initializing app-wide state using providers:
since we were able to fetch the current page's props, we could retrieve data
from the server (for example, the current user) and hydrate the
application's data
using Contexts, our other types of state management. It's simply a very
common pattern, that now no longer works the same way.

Normally, we can initialize the application's providers using the root
layout, and it will work in the same way as the old `_app.tsx` root component.

Unfortunately, if your application relies on data that needs to be passed down
from the server's response, we can not use the root layout since this
doesn't get the data passed from the page component: `Layout components` will only be
wrappers for the page components, e.g. their children props. Tricky, isn't it?

This is why the logic to initialize a page needs to be fetched by each page
component.

### Hydrating the Application's State: a practical example

Okay, enough talk, let's write some code.

What's a popular scenario for real
server-side rendered applications? One of them is passing the current
signed-in user to the page and hydrating a global context with the user's
data. This allows us to access the user's object throughout the application.

In the code below we abstract some implementation details such as
`getCurrentUser`: simply assume this function gets the current user using a
cookie, and it will throw if it fails.

```tsx
import { use } from 'react';
import { redirect } from 'next/navigation';
import { cookies } from "next/headers";

function Page() {
  const { data, action } = use(getPageData());

  if (action) {
    return action();
  }

  return <UserPage user={data} />;
}

async function getPageData() {
  const session = cookies().get('session');
  const redirectToLogin = () => redirect('/auth/sign-in');

  if (!session) {
    return {
      data: undefined,
      action: redirectToLogin,
    };
  }

  try {
    const data = await getUserBySessionId(session);

    return {
      data,
    };
  } catch (e) {
    return {
      data: undefined,
      action: redirectToLogin,
    };
  }
}

export default Page;
```

The above can definitely get way more complex in real applications,
especially if type-safe, but it should give you an idea of how you can reuse
functions across your pages and return a set of common data to your components.

The above takes care of fetching the data using a reusable function, but
does not show how to pass this down to a context function. To do that, we
need a `client component`, since we're going to use React's hooks such as
`useContext`.

To mark a component as a client component, Next.js uses a special string
`use client` at the top of the component's file:

```tsx
`use client`;

export default function Component() {}
```

So, we create a `UserContext` using the Context API to hold the state of the
signed in user.

```tsx
import { createContext } from 'react';
import { User } from './types';

const UserContext = createContext<User | undefined>(undefined);

export default UserContext;
```

Now we're going to define the component `UserPage` and pass the value
retrieved from the page.

**Just to test that it works**, we import the context
using `useContext` to display the current user's name using `UserRenderer`:

```tsx
'use client';

import { useContext } from 'react';

import { User } from './types';
import UserContext from './UserContext';

function UserPage(
  props: React.PropsWithChildren<{
    user: User;
  }>
) {
  return (
    <UserContext.Provider value={props.user}>
      <UserRenderer />
    </UserContext.Provider>
  );
}

function UserRenderer() {
  const user = useContext(UserContext);

  return <div>Ciao, {user?.displayName}</div>;
}

export default UserPage;
```

## Migrating from getServerSideProps

### Reading the URL Params

The page components receive props with two properties: `params` and
`searchParams`:

1. `params` are the page's segments
2. `queryParams` are the URL's query params

You can use these components to replace `getServerSideProps`'s `ctx`'s
parameters.

To read your query params, check the component below, that reads the `query`
parameter from the URL:

```tsx
function SearchPage(props: { searchParams: Record<string, string> }) {
  const query = props.searchParams.query;

  if (!query) {
    return redirect('/');
  }

  const data = use(getResultsFromQuery({ query, page: 0 }));

  // render function
```

To read the page's segments, instead, you can use `params`:

```tsx
function StoryPage(props: { params: Record<string, string> }) {
  const id = props.params.id;

  if (!id) {
    return redirect('/');
  }

  const item = use(getItemById(id));
  const comments = use(getCommentsByStoryId(id));

  // render function
```

### Reading Cookies and Headers

To read cookies and headers use the imports from the `next/headers` package:

```tsx
import { cookies, headers } from 'next/headers';

async function getPageData() {
  const session = cookies().get('session');
  const csrfToken = headers().get('csrfToken');
}
```

### Redirecting to other Pages

As we've seen above, you can use the `redirect` function from the new
`next/navigation` package to replace `{ redirect: { destination } }` props
that you used to use in `getServerSideProps`.

```tsx
import { redirect } from 'next/navigation';
import { cookies } from 'next/headers';

function Page() {
  const organizationId = cookies.get('organizationId');

  if (!organizationId) {
    return redirect('/auth/sign-in');
  }
}
```

### Redirecting when the page is not found

To redirect users to your `not-found.tsx` page, you need to use `notFound`
from the `next/navigation` package:

```tsx
import { notFound } from 'next/navigation';
import { cookies } from 'next/headers';

function Page() {
  const id = cookies.get('organizationId');
  const organization = use(getOrganization(id));

  if (!organization) {
    return notFound();
  }
}
```

And this it! This should give you a good idea of how the new utilities in
Next.js 13 can help you migrate from Next.js 12's `getServerSideProps` to
the new Server Components pages.

As I'm still learning and experimenting with this, please bear in mind there
could be mistakes. I will keep updating these articles as I uncover more
about Next.js 13 Layouts and Server Components. Ciao!
