JavaRush /Курсы /Модуль 4: Node.js, Next.js и Angular /Пример использования сессии в layout/page

Пример использования сессии в layout/page

Модуль 4: Node.js, Next.js и Angular
11 уровень , 4 лекция
Открыта

1. Для чего нужна сессия в layout/page?

В современных приложениях на Next.js сессия пользователя — это не просто “галочка” в чек-листе. Это основа для:

  • отображения персональной информации (например, приветствия по имени),
  • ограничения доступа к страницам или разделам сайта,
  • динамического формирования меню, кнопок “Войти/Выйти” и т.д.

Особенно удобно получать сессию в файлах layout.tsx или page.tsx, потому что они — входная точка для всего UI на уровне страницы или раздела. Здесь можно “протянуть” данные о пользователе во все дочерние компоненты.

Вспоминаем что возвращает функция auth():

В Next.js 15 с App Router (папка app/) вы можете получать сессию на сервере с помощью асинхронной функции auth() из next-auth. Она возвращает объект сессии пользователя (или null, если пользователь не авторизован).

Пример сессии:


{
  user: {
    name: "Иван Иванов",
    email: "ivan@example.com",
    image: "https://avatar.com/ivan.jpg"
  },
  expires: "2024-07-01T12:34:56.789Z"
}

2. Получаем сессию в layout.tsx

Давайте разберёмся, как получить и использовать сессию в корневом layout.

Шаг 1. Импортируем функцию auth

// app/layout.tsx
import { auth } from "@/auth"; // путь может отличаться в зависимости от вашей структуры

Важно:
Если вы следуете документации next-auth, функцию auth нужно экспортировать из вашего файла конфигурации next-auth (например, auth.ts или auth.js в корне проекта или в папке lib/).

Шаг 2. Делаем layout асинхронным

Поскольку auth() — асинхронная функция, ваш компонент layout должен быть async:


export default async function RootLayout({ children }) {
  const session = await auth();

  return (
    <html lang="ru">
      <body>
        {/* Передаём сессию в навигацию, шапку или куда угодно */}
        <Header session={session} />
        <main>{children}</main>
      </body>
    </html>
  );
}

Шаг 3. Используем session в дочерних компонентах

Создайте, например, компонент Header, который будет показывать имя пользователя и кнопку “Войти/Выйти” в зависимости от того, есть ли сессия.


// components/Header.tsx
export default function Header({ session }) {
  return (
    <header style={{ padding: 16, borderBottom: "1px solid #eee" }}>
      {session?.user ? (
        <span>
          Привет, {session.user.name}!{" "}
          <a href="/api/auth/signout">Выйти</a>
        </span>
      ) : (
        <a href="/api/auth/signin">Войти</a>
      )}
    </header>
  );
}

Шутка для разрядки:
Пользователь без сессии — как фронтендер без кофе: вроде бы работает, но удовольствия мало.

3. Получение сессии в page.tsx

Точно так же вы можете получить сессию в любом файле page.tsx, если он асинхронный.


// app/page.tsx
import { auth } from "@/auth";

export default async function HomePage() {
  const session = await auth();

  return (
    <section>
      <h1>Главная страница</h1>
      {session?.user ? (
        <p>Добро пожаловать, {session.user.name}!</p>
      ) : (
        <p>Пожалуйста, <a href="/api/auth/signin">войдите</a> для продолжения.</p>
      )}
    </section>
  );
}

4. Пример: защищаем страницу только для авторизованных

Допустим, у нас есть страница профиля, которую должен видеть только залогиненный пользователь. Как это сделать?


// app/profile/page.tsx
import { auth } from "@/auth";
import { redirect } from "next/navigation";

export default async function ProfilePage() {
  const session = await auth();

  if (!session?.user) {
    // Пользователь не авторизован — отправим его на главную
    redirect("/");
  }

  return (
    <div>
      <h2>Профиль пользователя</h2>
      <p>Имя: {session.user.name}</p>
      <p>Email: {session.user.email}</p>
      <img src={session.user.image} alt="аватар" width={64} height={64} />
    </div>
  );
}

Обратите внимание:
Функция redirect() работает только на сервере (то есть в Server Component или в асинхронном обработчике). На клиенте используйте хук useRouter().push().

5. Передача сессии вниз по дереву через пропсы или Context

Если вам нужно “протянуть” сессию глубоко в дерево компонентов, два варианта:

  1. Передавать через пропсы (как в примере с Header выше).
  2. Создать React Context и обернуть нужные компоненты.

Пример Context (Server Component):


// lib/SessionContext.tsx
import { createContext } from "react";

export const SessionContext = createContext(null);

// app/layout.tsx
import { SessionContext } from "@/lib/SessionContext";
import { auth } from "@/auth";

export default async function RootLayout({ children }) {
  const session = await auth();

  return (
    <html lang="ru">
      <body>
        <SessionContext.Provider value={session}>
          <Header />
          <main>{children}</main>
        </SessionContext.Provider>
      </body>
    </html>
  );
}

В дочерних компонентах:


import { useContext } from "react";
import { SessionContext } from "@/lib/SessionContext";

export default function UserInfo() {
  const session = useContext(SessionContext);

  if (!session?.user) return null;
  return <div>Пользователь: {session.user.name}</div>;
}

Важно:
Контекст работает только в Client Components. Если вы хотите использовать session в Client Component, не забудьте добавить 'use client' в начало файла.

6. Как это выглядит в реальном приложении

Вот схема, как данные о сессии “текут” через ваше приложение:


┌────────────┐
│ layout.tsx │
└─────┬──────┘
      │ (await auth())
      ▼
┌────────────┐
│  Header    │ ← session через пропсы
└────────────┘
      │
      ▼
┌────────────┐
│  Main      │
│  (children)│
└────────────┘
      │
      ▼
┌────────────┐
│  Page      │ ← session через пропсы или Context
└────────────┘

7. Типичные ошибки при работе с сессией в layout/page

Ошибка №1: забыли сделать компонент асинхронным.
Если вы используете await auth(), ваш компонент должен быть async. Если забыли — получите ошибку компиляции или “Unexpected token”.

Ошибка №2: неверный импорт функции auth.
Проверьте путь к вашей функции auth. В Next.js 15 структура может быть разной, не всегда это next-auth/react.

Ошибка №3: попытка использовать session в Client Component без передачи через пропсы или Context.
Функция auth() работает только на сервере. Для Client Components прокидывайте session через пропсы или Context.

Ошибка №4: попытка вызвать redirect() на клиенте.
Функция redirect() работает только на сервере. Для клиента используйте хук useRouter.

Ошибка №5: забыли обработать случай, когда session равен null.
Пользователь может быть не авторизован! Не забывайте проверять session?.user перед выводом личной информации.

3
Опрос
Аутентификация с next-auth, 11 уровень, 4 лекция
Недоступен
Аутентификация с next-auth
Аутентификация с next-auth
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ