Настройка темы для Next JS

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

Привет, я новичок в Next.js. Когда я пытаюсь настроить и разделить компоненты, такие как Header, Footer, Sidebar, и обновить эти компоненты в Layout.tsx, мне не удается передать свойства между ними, так как Layout.tsx является основным файлом, где Next.js предоставляет путь для обновления шаблонов/тем.

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

"use client";
import React, { useState } from 'react';

export default function Home() {
  const [sidebarOpen, setSidebarOpen] = useState(true);
  const [hoverSidebar, setHoverSidebar] = useState(false);
  const [activeDropdown, setActiveDropdown] = useState(null);
  const [profileDropdownOpen, setProfileDropdownOpen] = useState(false);

  const handleSidebarToggle = () => {
    setSidebarOpen(!sidebarOpen);
  };

  const toggleDropdown = (menu: any) => {
    setActiveDropdown(activeDropdown === menu ? null : menu);
  };

  const toggleProfileDropdown = () => {
    setProfileDropdownOpen(!profileDropdownOpen);
  };

  return (
    <>
      <div className="flex h-screen">
        {/* Sidebar */}
        <div
          className={`${sidebarOpen || hoverSidebar ? 'w-64' : 'w-16'} bg-gray-800 text-white transition-all duration-300 relative`}
          onMouseEnter={() => setHoverSidebar(true)}
          onMouseLeave={() => setHoverSidebar(false)}
        >
          <div className="flex flex-col h-full">
            <div className="p-3 bg-gray-900 flex items-center">
              <img src="https://placeholderimage/500" alt="Логотип" className="w-8 h-8 rounded-full" />
              <span className={`${sidebarOpen || hoverSidebar ? 'ml-3' : 'hidden'} text-xl font-bold`}>Тестовое приложение</span>
            </div>

            <nav className="flex-1 mt-4">
              <a href="#" className="flex items-center py-3 px-4 hover:bg-gray-700 w-full">
                <i className="fa-solid fa-gauge mr-3"></i>
                <span className={`${sidebarOpen || hoverSidebar ? 'block' : 'hidden'}`}>Панель управления</span>
              </a>
              <div>
                <button
                  className="flex items-center py-3 px-4 hover:bg-gray-700 w-full focus:outline-none"
                  onClick={() => toggleDropdown('profile')}
                >
                  <i className="fas fa-user mr-3"></i>
                  <span className={`${sidebarOpen || hoverSidebar ? 'block' : 'hidden'}`}>Профиль</span>
                  {(sidebarOpen || hoverSidebar) && (
                    <i
                      className={`fas fa-chevron-down ml-auto ${activeDropdown === 'profile' ? 'rotate-180' : ''} transition-transform`}
                    ></i>
                  )}
                </button>
                {activeDropdown === 'profile' && (
                  <div className={`${sidebarOpen || hoverSidebar ? 'block' : 'hidden'} bg-gray-700`}>
                    <a href="#" className="block px-6 py-2 hover:bg-gray-600">Сменить пароль</a>
                    <a href="#" className="block px-6 py-2 hover:bg-gray-600">Обновить профиль</a>
                  </div>
                )}
              </div>
              <div>
                <button
                  className="flex items-center py-3 px-4 hover:bg-gray-700 w-full focus:outline-none"
                  onClick={() => toggleDropdown('course')}
                >
                  <i className="fas fa-book mr-3"></i>
                  <span className={`${sidebarOpen || hoverSidebar ? 'block' : 'hidden'}`}>Курс</span>
                  {(sidebarOpen || hoverSidebar) && (
                    <i
                      className={`fas fa-chevron-down ml-auto ${activeDropdown === 'course' ? 'rotate-180' : ''} transition-transform`}
                    ></i>
                  )}
                </button>
                {activeDropdown === 'course' && (
                  <div className={`${sidebarOpen || hoverSidebar ? 'block' : 'hidden'} bg-gray-700`}>
                    <a href="#" className="block px-6 py-2 hover:bg-gray-600">Создать курс</a>
                    <a href="#" className="block px-6 py-2 hover:bg-gray-600">Список курсов</a>
                  </div>
                )}
              </div>
            </nav>
          </div>
        </div>

        {/* Основное содержимое */}
        <div className="flex-1 flex flex-col bg-gray-100">
          <header style={{ backgroundColor: '#115e59' }} className="text-white shadow p-2 flex justify-between items-center">
            <div className="flex items-center">
              <button onClick={handleSidebarToggle} className="p-2 focus:outline-none">
                <i className={`fas ${sidebarOpen ? 'fa-chevron-left' : 'fa-chevron-right'}`}></i>
              </button>
              <h1 className="ml-3 text-xl font-bold">Панель управления</h1>
            </div>
            <div className="relative">
              <button style={{ backgroundColor: '#17a2b8' }} className="flex items-center px-2 py-1 text-white rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50 transition duration-150 ease-in-out">
                <i className="fas fa-sign-out mr-2"></i>
                <span>Выйти</span>
              </button>
            </div>
          </header>

          <main className="p-4 flex-1 overflow-y-auto">
            <div className="max-w-full p-2">
              <div className="bg-white shadow-md rounded-lg">
                <div className="text-white p-3 rounded-t-lg" style={{ backgroundColor: '#138597' }}>
                  {/* Заголовок карточки */}
                  <h2 className="text-xl font-semibold">Название карточки</h2>
                </div>
                <div className="p-6"> {/* Содержимое карточки */}
                  <p className="text-gray-700">
                    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
                  </p>
                </div>
              </div>
            </div>
          </main>

          {/* Нижний колонтитул */}
          <footer style={{ backgroundColor: '#115e59' }} className="text-white p-1 text-center">
            <p className="text-sm">© 2024 Ваша компания. Все права защищены.</p>
          </footer>
        </div>
      </div>
    <>
  );
}

Пожалуйста, помогите мне разделить файл на Header, Footer, Sidebar и обновить их в файле Layout.tsx.

Заранее спасибо…

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

Настройка темы для Next.js может показаться сложной задачей для новичков, особенно при попытке организовать компоненты, такие как Header, Footer и Sidebar. Ниже представлена подробная инструкция, как можно реализовать эти компоненты и передавать им необходимые пропсы, используя файл Layout.tsx.

1. Создание компонентов

Сначала создадим три отдельных файла для компонентов: Header.tsx, Footer.tsx и Sidebar.tsx. Каждый из этих компонентов будет принимать необходимые пропсы.

Header.tsx

import React from 'react';

interface HeaderProps {
  sidebarOpen: boolean;
  handleSidebarToggle: () => void;
}

const Header: React.FC<HeaderProps> = ({ sidebarOpen, handleSidebarToggle }) => {
  return (
    <header style={{ backgroundColor: '#115e59' }} className="text-white shadow p-2 flex justify-between items-center">
      <div className="flex items-center">
        <button onClick={handleSidebarToggle} className="p-2 focus:outline-none">
          <i className={`fas ${sidebarOpen ? 'fa-chevron-left' : 'fa-chevron-right'}`}></i>
        </button>
        <h1 className="ml-3 text-xl font-bold">Dashboard</h1>
      </div>
      {/* Остальная часть Header */}
    </header>
  );
};

export default Header;

Footer.tsx

import React from 'react';

const Footer: React.FC = () => {
  return (
    <footer style={{ backgroundColor: '#115e59' }} className="text-white p-1 text-center">
      <p className="text-sm">© 2024 Ваша Компания. Все права защищены.</p>
    </footer>
  );
};

export default Footer;

Sidebar.tsx

import React from 'react';

interface SidebarProps {
  sidebarOpen: boolean;
  setSidebarOpen: (open: boolean) => void;
  hoverSidebar: boolean;
  setHoverSidebar: (hover: boolean) => void;
  activeDropdown: string | null;
  toggleDropdown: (menu: string) => void;
}

const Sidebar: React.FC<SidebarProps> = ({
  sidebarOpen,
  setSidebarOpen,
  hoverSidebar,
  setHoverSidebar,
  activeDropdown,
  toggleDropdown,
}) => {
  return (
    <div
      className={`${sidebarOpen || hoverSidebar ? 'w-64' : 'w-16'} bg-gray-800 text-white transition-all duration-300 relative`}
      onMouseEnter={() => setHoverSidebar(true)}
      onMouseLeave={() => setHoverSidebar(false)}
    >
      {/* Код для Sidebar */}
    </div>
  );
};

export default Sidebar;

2. Настройка Layout.tsx

Теперь нужно создать Layout.tsx, в котором мы будем собирать наши компоненты.

import React, { useState } from 'react';
import Header from './Header';
import Footer from './Footer';
import Sidebar from './Sidebar';

const Layout: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [sidebarOpen, setSidebarOpen] = useState(true);
  const [hoverSidebar, setHoverSidebar] = useState(false);
  const [activeDropdown, setActiveDropdown] = useState<string | null>(null);

  const handleSidebarToggle = () => {
    setSidebarOpen(!sidebarOpen);
  };

  const toggleDropdown = (menu: string) => {
    setActiveDropdown(activeDropdown === menu ? null : menu);
  };

  return (
    <div className="flex h-screen">
      <Sidebar
        sidebarOpen={sidebarOpen}
        setSidebarOpen={setSidebarOpen}
        hoverSidebar={hoverSidebar}
        setHoverSidebar={setHoverSidebar}
        activeDropdown={activeDropdown}
        toggleDropdown={toggleDropdown}
      />
      <div className="flex-1 flex flex-col bg-gray-100">
        <Header sidebarOpen={sidebarOpen} handleSidebarToggle={handleSidebarToggle} />
        <main className="p-4 flex-1 overflow-y-auto">
          {children}
        </main>
        <Footer />
      </div>
    </div>
  );
};

export default Layout;

3. Использование Layout в вашем приложении

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

Пример page.js

import React from 'react';
import Layout from '../components/Layout';

const Home: React.FC = () => {
  return (
    <Layout>
      {/* Ваш контент страницы здесь */}
      <h2 className="text-xl font-semibold">Главная страница</h2>
      <p>Содержимое вашей главной страницы.</p>
    </Layout>
  );
};

export default Home;

Заключение

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

Если у вас остаются вопросы, не стесняйтесь обращаться за помощью!

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

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