Передача пропсов и их типизация

Основы передачи пропсов

Компоненты MUI (Material-UI) в React проектируются с учетом гибкости и расширяемости, поэтому большинство компонентов поддерживают передачу пропсов, позволяющих настраивать внешний вид и поведение компонентов. Пропсы могут быть стандартными (например, className, style) или специфичными для MUI (например, variant, color, size).

Пример передачи базовых пропсов:

import Button from '@mui/material/Button';

function App() {
  return (
    <Button variant="contained" color="primary" size="large">
      Нажми меня
    </Button>
  );
}

Здесь variant, color и size — это пропсы, которые компонент Button обрабатывает внутри себя и использует для генерации стилей.

Спред-пропсы и наследование атрибутов

Часто возникает необходимость передать все свойства родительского элемента в дочерний компонент, не перечисляя их по одному. Для этого используется спред-оператор:

function CustomButton(props) {
  return <Button {...props} />;
}

<CustomButton variant="outlined" color="secondary" onCl ick={() => console.log('Clicked')} />;

Использование {...props} позволяет дочернему компоненту принимать любые дополнительные атрибуты, включая стандартные HTML-атрибуты (id, title, aria-*) и специфичные для MUI.

Контроль типов с TypeScript

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

import { Button, ButtonProps } from '@mui/material';

interface CustomButtonProps extends ButtonProps {
  highlight?: boolean;
}

const CustomButton: React.FC<CustomButtonProps> = ({ highlight, ...props }) => {
  return (
    <Button
      {...props}
      style={{
        backgroundColor: highlight ? 'yellow' : undefined,
        ...props.style
      }}
    />
  );
};
  • ButtonProps — встроенный интерфейс, предоставляемый MUI, который содержит все допустимые пропсы для компонента Button.
  • Дополнительные свойства (highlight) можно объявить через собственный интерфейс, расширяющий базовый тип.

Передача функций и обработчиков событий

MUI компоненты используют типизированные обработчики событий React. Например, onClick имеет тип (event: React.MouseEvent<HTMLButtonElement>) => void.

<Button
  onCl ick={(event) => {
    console.log('Кликнули!', event.currentTarget);
  }}
>
  Click me
</Button>

Типизация событий особенно важна при использовании TypeScript, так как позволяет IDE предоставлять автодополнение и проверку типов.

Пропсы для управления стилями

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

  • sx-пропс — мощный способ описания стилей через объект:
<Button sx={{ backgroundColor: 'green', padding: 2 }}>
  Зеленая кнопка
</Button>
  • className — для добавления собственных CSS-классов:
<Button className="my-button">
  Кнопка с классом
</Button>
  • styled API — создание полностью типизированных компонентов с кастомными стилями:
import { styled } from '@mui/material/styles';
import Button from '@mui/material/Button';

const MyButton = styled(Button)<{ highlight?: boolean }>(({ highlight }) => ({
  backgroundColor: highlight ? 'orange' : 'blue',
  color: '#fff',
  '&:hover': {
    backgroundColor: highlight ? 'darkorange' : 'darkblue',
  },
}));

<MyButton highlight>Кастомная кнопка</MyButton>

Передача пропсов дочерним компонентам

Иногда необходимо, чтобы дочерний компонент получал только определённые пропсы из родителя. Для этого используют деструктуризацию:

interface CardProps {
  title: string;
  content: string;
  onClick?: () => void;
}

const Card: React.FC<CardProps> = ({ title, content, onClick }) => {
  return (
    <div onCl ick={onClick} className="card">
      <h3>{title}</h3>
      <p>{content}</p>
    </div>
  );
};

<Card title="Заголовок" content="Текст карточки" onCl ick={() => alert('Clicked')} />;

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

Полезные рекомендации по типизации пропсов

  1. Использовать встроенные типы MUI (ButtonProps, TextFieldProps, PaperProps) для всех стандартных компонентов.
  2. Расширять базовые типы для собственных кастомных пропсов.
  3. Типизировать обработчики событий для точного автокомплита и безопасной работы с событиями.
  4. Использовать Omit или Pick для выборочной модификации пропсов при создании обёрток:
interface CustomTextFieldProps extends Omit<TextFieldProps, 'variant'> {
  customVariant?: 'fancy' | 'simple';
}
  1. sx-пропс и styled API полностью типизированы, что позволяет писать сложные стили без потери проверки типов.

Особенности передачи пропсов в MUI v5

  • Компоненты MUI v5 используют emotion или styled-components, что улучшает работу с типами для стилей.
  • Практически все компоненты поддерживают forwardRef, позволяя передавать рефы через пропсы ref.
  • Пропсы типа component позволяют заменять базовый HTML-элемент на кастомный, сохраняя типизацию всех остальных атрибутов:
<Button component="a" href="/home">
  Ссылка
</Button>

Итоговая структура безопасной передачи пропсов

  1. Базовые пропсы MUI наследуются через встроенные интерфейсы.
  2. Дополнительные кастомные пропсы добавляются через расширение интерфейса.
  3. Спред-оператор {...props} используется для передачи всех оставшихся пропсов.
  4. Типизация событий и стилей обеспечивает безопасную интеграцию и автодополнение в редакторах.
  5. Использование sx и styled позволяет комбинировать стили MUI и кастомные стили без конфликтов типов.

Такой подход к передаче пропсов и их типизации обеспечивает гибкость, безопасность и совместимость с современными стандартами React и MUI, позволяя создавать масштабируемые интерфейсы с предсказуемым поведением компонентов.