Вопрос или проблема
Я разрабатываю веб-приложение на 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.
.
Решение
Чтобы создать разные макеты для разных сегментов вашего приложения, вам нужно будет:
-
Удалить корневой макет из корневой директории: Убедитесь, что у вас нет файла
app/layout.tsx
в корне вашего приложения. Вместо этого вы будете использовать макеты в каждом сегменте. -
Создать макеты в сегментах: Создайте
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>
);
}
Убедитесь в следующем:
- Удалите файл
app/layout.tsx
, чтобы избежать дублирования корневого HTML. - Параметризуйте
children
и используйте правильные HTML-теги только в администраторском макете. - При необходимости создайте и используйте вложенные макеты для разделения логики рендеринга между различными частями вашего приложения.
Следуя описанным шагам, вы сможете создать конкретные макеты для разных маршрутов, что поможет избежать конфликтов и ошибок рендеринга. Надеюсь, это поможет вам в разработке вашего приложения на Next.js!