Организация компонентов

MUI (Material-UI) предоставляет мощный набор компонентов для построения интерфейсов на JavaScript и React. Эффективная организация компонентов позволяет создавать масштабируемые, поддерживаемые и переиспользуемые интерфейсы. Основные принципы организации включают иерархию компонентов, разделение логики и презентации и использование тематических и стилизованных компонентов.


Иерархия компонентов

Компоненты в MUI можно разделить на три уровня:

  1. Атомарные компоненты (Atoms) Это базовые элементы интерфейса: Button, TextField, Checkbox. Они редко содержат сложную логику и используются как строительные блоки. Пример атомарного компонента с MUI:
import Button from '@mui/material/Button';

function PrimaryButton({ label, onClick }) {
  return (
    <Button variant="contained" color="primary" onCl ick={onClick}>
      {label}
    </Button>
  );
}
  1. Составные компоненты (Molecules) Комбинируют несколько атомарных компонентов для решения небольшой задачи. Например, форма поиска с TextField и Button:
import TextField from '@mui/material/TextField';
import Button from '@mui/material/Button';
import Box from '@mui/material/Box';

function SearchForm({ value, onChange, onSubmit }) {
  return (
    <Box component="form" onSub mit={onSubmit} display="flex" gap={1}>
      <TextField value={value} onCha nge={onChange} placeholder="Поиск..." />
      <Button type="submit" variant="contained">Найти</Button>
    </Box>
  );
}
  1. Структурные компоненты (Organisms) Создают крупные блоки интерфейса, объединяя молекулы и атомы. Пример: шапка приложения с меню и поиском:
import AppBar from '@mui/material/AppBar';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import SearchForm from './SearchForm';

function Header() {
  return (
    <AppBar position="static">
      <Toolbar>
        <Typography variant="h6" sx={{ flexGrow: 1 }}>Мой сайт</Typography>
        <SearchForm />
      </Toolbar>
    </AppBar>
  );
}

Разделение логики и презентации

MUI позволяет отделять логику работы компонента от его визуального представления, что повышает переиспользуемость. Обычно создаются два типа компонентов:

  • Контейнерные (Container/Smart) компоненты — отвечают за состояние, API-запросы, обработку событий.
  • Презентационные (Presentational/Dumb) компоненты — отвечают только за отображение данных и принимают их через пропсы.

Пример разделения:

// Контейнер
function UserProfileContainer({ userId }) {
  const [user, setUser] = React.useState(null);

  React.useEffect(() => {
    fetch(`/api/users/${userId}`)
      .then(res => res.json())
      .then(setUser);
  }, [userId]);

  if (!user) return null;

  return <UserProfileCard user={user} />;
}

// Презентационный компонент
import Card from '@mui/material/Card';
import CardContent from '@mui/material/CardContent';
import Typography from '@mui/material/Typography';

function UserProfileCard({ user }) {
  return (
    <Card>
      <CardContent>
        <Typography variant="h5">{user.name}</Typography>
        <Typography variant="body2">{user.email}</Typography>
      </CardContent>
    </Card>
  );
}

Использование систем стилей и тем

MUI предлагает мощную систему стилизации через sx-проп, styled API и ThemeProvider. Это позволяет создавать единый визуальный язык для приложения.

Пример использования sx для кастомизации:

<Box sx={{ display: 'flex', gap: 2, p: 2, bgcolor: 'background.paper' }}>
  <Button variant="contained" color="secondary">Кнопка 1</Button>
  <Button variant="outlined" color="primary">Кнопка 2</Button>
</Box>

Создание пользовательской темы:

import { createTheme, ThemeProvider } from '@mui/material/styles';

const theme = createTheme({
  palette: {
    primary: { main: '#1976d2' },
    secondary: { main: '#dc004e' },
  },
  typography: {
    h6: { fontWeight: 600 },
  },
});

function App() {
  return (
    <ThemeProvider theme={theme}>
      <Header />
      <MainContent />
    </ThemeProvider>
  );
}

Переиспользуемые компоненты и композиция

MUI поддерживает композицию компонентов через пропсы children и HOC (Higher Order Components). Это облегчает создание универсальных компонентов, которые можно адаптировать под разные задачи.

function CardWrapper({ children, title }) {
  return (
    <Card sx={{ mb: 2 }}>
      {title && <Typography variant="h6" sx={{ p: 2 }}>{title}</Typography>}
      {children}
    </Card>
  );
}

// Использование
<CardWrapper title="Информация о пользователе">
  <UserProfileCard user={user} />
</CardWrapper>

Организация файловой структуры

Для больших проектов структура может быть следующей:

/components
  /atoms
    Button.js
    TextField.js
  /molecules
    SearchForm.js
  /organisms
    Header.js
  /pages
    HomePage.js
    ProfilePage.js

Рекомендации:

  • Атомы и молекулы не должны импортировать структурные компоненты.
  • Структурные компоненты объединяют нижележащие уровни.
  • Логика данных и визуализация разделяются на контейнеры и презентационные компоненты.

Состояние и контекст

Для управления состоянием интерфейса используют React Context или глобальные стейты (Redux, Zustand). MUI компоненты легко интегрируются с контекстом для темизации, авторизации и глобальных настроек интерфейса.

Пример контекста темы:

import { createContext, useContext, useState } from 'react';

const ThemeModeContext = createContext();

export function ThemeModeProvider({ children }) {
  const [mode, setMode] = useState('light');
  const toggleMode = () => setMode(prev => prev === 'light' ? 'dark' : 'light');

  return (
    <ThemeModeContext.Provider value={{ mode, toggleMode }}>
      {children}
    </ThemeModeContext.Provider>
  );
}

export function useThemeMode() {
  return useContext(ThemeModeContext);
}

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