Как использовать пользовательскую верстку для определенных маршрутов

Вопрос или проблема

Я разрабатываю веб-приложение на React с использованием Next.JS, которое разделено на 2 основные части: пользовательскую сторону и административную сторону. Мне нужно использовать другой макет для всех моих административных страниц, но я столкнулся с несколькими проблемами.

Вот структура файлов:

├─ about-us/
│  └─ page.tsx
├─ admin/
│  ├─ tracking/
│  │  └─ create/
│  │     └─ page.tsx
│  ├─ AdminDashboardClient.tsx
│  ├─ layout.tsx
│  └─ page.tsx
├─ assets/
│  └─ images/
├─ careers/
│  └─ page.tsx
├─ contact/
│  └─ page.tsx
├─ fonts/
│  ├─ GeistMonoVF.woff
│  └─ GeistVF.woff
├─ shipping/
│  └─ page.tsx
├─ track/
│  └─ page.tsx
├─ favicon.ico
├─ globals.css
├─ layout.tsx
└─ page.tsx

admin/layout.tsx:

import React from 'react'
import Link from 'next/link'
import { Home, Package, Users, Settings } from 'lucide-react'

export const metadata = {
title: 'Админская панель',
description: 'Админская панель корабельной компании',
}

export default function AdminRootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
   <html lang="en">
     <body className="bg-gray-100">
       <div className="flex min-h-screen">
          {/\* Боковая панель \*/}

          {/* Основное содержимое */}
          <main className="flex-1 overflow-x-hidden overflow-y-auto">
            <div className="container mx-auto px-6 py-8">
              {children}
            </div>
          </main>
        </div>
      </body>
    </html>

)
}

layout.tsx:

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <body
        className={`${geistSans.variable} ${geistMono.variable} antialiased`}
      >
        <Header />
        {children}
        <Footer />
      </body>
    </html>
  );
}

Основная проблема заключается в том, что как Header, так и Footer загружаются на административных страницах, кроме боковой панели из admin/layout.tsx. Я считаю, что это также вызывает Ошибка: Содержимое текста не соответствует HTML, отрендеренному сервером. на административных страницах. Заголовок ведет себя странно, так как он появляется на одну секунду, а затем исчезает.

Я ожидаю получить специфичный макет для страниц под маршрутом администратора.

Решение этой проблемы – использовать Сегменты маршрутов.

Используя теги html или body в макете, вы определяете корневой макет.

У вас должен быть только один корневой макет. Или один на сегмент. Но никогда один в корне и один в сегменте. Поэтому здесь вы удаляете app/layout и имеете один в каждом сегменте.

Из документации:

Создание нескольких корневых макетов

Чтобы создать несколько корневых макетов, удалите файл top-level layout.js, и добавьте файл layout.js внутри каждой группы маршрутов. Это полезно для разбиения приложения на секции с совершенно различным пользовательским интерфейсом или опытом. Теги html и body должны быть добавлены к каждому корневому макету.

Структура:

  app
    (main)
      about-us
        page.jsx
      page.jsx
      layout.jsx # корневой макет
    (admin)
        admin
          tracking
            create
              page.jsx
      page.jsx
      layout.jsx # корневой макет

Также рассмотрите возможность удаления визуальных компонентов из корневого макета, а затем вложения макетов с визуальными компонентами. Смотрите как

Ответ или решение

Для реализации пользовательского макета для конкретных маршрутов в приложении на Next.js, вам необходимо правильно организовать структуру файлов и удалить ненужные компоненты из корневого макета. Давайте разберем вашу ситуацию и предложим решение.

Проблема

Вы пробуете использовать два макета: один для пользовательской стороны и другой для администраторской. Однако, поскольку у вас оба макета имеют корневые элементы <html> и <body>, это приводит к конфликтам и ошибкам при рендеринге, таким как Error: Text content does not match server-rendered HTML..

Решение

Чтобы создать разные макеты для разных сегментов вашего приложения, вам нужно будет:

  1. Удалить корневой макет из корневой директории: Убедитесь, что у вас нет файла app/layout.tsx в корне вашего приложения. Вместо этого вы будете использовать макеты в каждом сегменте.

  2. Создать макеты в сегментах: Создайте layout.tsx файлы внутри групп маршрутов, где вам нужен определенный макет. Например, в вашем случае это будет admin/layout.tsx.

Структура файлов

Измененная структура файлов может выглядеть так:

app
├─ (main)
│  ├─ about-us/
│  │  └─ page.tsx
│  ├─ careers/
│  │  └─ page.tsx
│  ├─ contact/
│  │  └─ page.tsx
│  ├─ shipping/
│  │  └─ page.tsx
│  └─ track/
│     └─ page.tsx
├─ (admin)
│  ├─ layout.tsx      // Это ваш макет для администраторов
│  ├─ admin/
│  │  ├─ tracking/
│  │  │  └─ create/
│  │  │     └─ page.tsx
│  │  ├─ AdminDashboardClient.tsx
│  │  └─ page.tsx
└─ favicon.ico

Пример кода для admin/layout.tsx

Вот как должен выглядеть ваш admin/layout.tsx:

import React from 'react';
import Link from 'next/link';
import { Home, Package, Users, Settings } from 'lucide-react';

export const metadata = {
  title: 'Admin Dashboard',
  description: 'Shipping Company Admin Dashboard',
};

export default function AdminRootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body className="bg-gray-100">
        <div className="flex min-h-screen">
          {/* Ваш сайдбар */}
          <aside className="w-64 bg-white border-r">
            {/* Ссылки на админ страницу */}
            <nav>
              <Link href="/admin/dashboard">Dashboard</Link>
              <Link href="/admin/tracking/create">Create Tracking</Link>
              {/* Другие ссылки */}
            </nav>
          </aside>

          {/* Основное содержимое */}
          <main className="flex-1 overflow-x-hidden overflow-y-auto">
            <div className="container mx-auto px-6 py-8">
              {children}
            </div>
          </main>
        </div>
      </body>
    </html>
  );
}

Убедитесь в следующем:

  1. Удалите файл app/layout.tsx, чтобы избежать дублирования корневого HTML.
  2. Параметризуйте children и используйте правильные HTML-теги только в администраторском макете.
  3. При необходимости создайте и используйте вложенные макеты для разделения логики рендеринга между различными частями вашего приложения.

Следуя описанным шагам, вы сможете создать конкретные макеты для разных маршрутов, что поможет избежать конфликтов и ошибок рендеринга. Надеюсь, это поможет вам в разработке вашего приложения на Next.js!

Оцените материал
Добавить комментарий

Капча загружается...