Паттерн для создания связанных компонентов, которые работают вместе для обеспечения сложного поведения, сохраняя при этом гибкость и переиспользуемость.
Следование общим правилам
Особенности compound components
user-form/
├── user-form.form.tsx # Основной файл с compound components
├── user-form.form.module.css # Стили
└── user-form.form.test.ts # Тесты
user-form/
├── user-form.form.tsx # Основной файл с compound components
├── user-form.form.module.css # Стили
├── user-form.form.test.ts # Тесты
└── components/ # Опционально: сложные компоненты
├── fields/
│ ├── user-fields.component.tsx
│ └── user-fields.component.module.css
└── actions/
├── form-actions.component.tsx
└── form-actions.component.module.css
// user-form.form.tsx
'use client';
import { UserFields } from './components/fields/user-fields.component';
import { FormActions } from './components/actions/form-actions.component';
import styles from './user-form.form.module.css';
// Общие типы для формы
type FormData = {
name: string;
email: string;
};
// Root компонент
function Root({
onSubmit,
children,
}: {
onSubmit: (data: FormData) => void;
children: React.ReactNode;
}) {
return (
<form className={styles.form} onSubmit={handleSubmit}>
{children}
</form>
);
}
// Header компонент
function Header({ title }: { title: string }) {
return <div className={styles.header}>{title}</div>;
}
// Footer компонент
function Footer({ children }: { children: React.ReactNode }) {
return <div className={styles.footer}>{children}</div>;
}
// Экспорт через объект
export const UserForm = {
Root,
Header,
Footer,
Fields: UserFields, // Импортированная имплементация
Actions: FormActions, // Импортированная имплементация
};
// components/fields/user-fields.component.tsx
import styles from './user-fields.component.module.css';
export function UserFields({
values,
onChange,
}: {
values: FormData;
onChange: (field: keyof FormData, value: string) => void;
}) {
return (
<div className={styles.fields}>
<input
value={values.name}
onChange={(e) => onChange('name', e.target.value)}
/>
<input
value={values.email}
onChange={(e) => onChange('email', e.target.value)}
/>
</div>
);
}
function UserManagement() {
return (
<UserForm.Root onSubmit={handleSubmit}>
<UserForm.Header title="Создание пользователя" />
<UserForm.Fields values={values} onChange={handleChange} />
<UserForm.Footer>
<UserForm.Actions onCancel={handleCancel} />
</UserForm.Footer>
</UserForm.Root>
);
}
Организация кода
Переиспользование
Поддерживаемость
Именование
Типизация
Организация