К списку правил

Правила оформления компонентов

Основные правила

  1. Объявление компонентов через function
  2. Использование инлайн типов
  3. Файлы рядом с компонентом

Структура файлов

user-table/
├── user-table.component.tsx
├── user-table.component.module.css
└── user-table.component.test.ts

user-form/
├── user-form.form.tsx
├── user-form.form.module.css
└── user-form.form.test.ts

Объявление компонентов

// ❌ НЕ ПРАВИЛЬНО - стрелочная функция
const UserTable = () => {
    return <div>Table</div>;
};

// ❌ НЕ ПРАВИЛЬНО - именованное выражение
const UserTable = function UserTable() {
    return <div>Table</div>;
};

// ✅ ПРАВИЛЬНО - объявление функции
export function UserTable() {
    return <div>Table</div>;
}

Типизация пропсов

// ❌ НЕ ПРАВИЛЬНО - отдельный интерфейс
interface UserTableProps {
    users: User[];
    onEdit: (id: number) => void;
}

export function UserTable(props: UserTableProps) {
    return <div>Table</div>;
}

// ✅ ПРАВИЛЬНО - инлайн типы
export function UserTable({
    users,
    onEdit,
}: {
    users: User[];
    onEdit: (id: number) => void;
}) {
    return <div>Table</div>;
}

Структура компонента

'use client'; // Если компонент клиентский

// 1. Импорты
import { useState } from 'react';
import styles from './user-table.component.module.css';

// 2. Компонент
export function UserTable({
    users,
    onEdit,
}: {
    users: User[];
    onEdit: (id: number) => void;
}) {
    // 2.1 Хуки
    const [selectedId, setSelectedId] = useState<number | null>(null);

    // 2.2 Обработчики
    function handleEdit(id: number) {
        setSelectedId(id);
        onEdit(id);
    }

    // 2.3 Рендер
    return (
        <div className={styles.table}>
            {users.map((user) => (
                <div key={user.id} className={styles.row}>
                    <span>{user.name}</span>
                    <button onClick={() => handleEdit(user.id)}>
                        Edit
                    </button>
                </div>
            ))}
        </div>
    );
}

CSS Modules

/* user-table.component.module.css */
.table {
	width: 100%;
}

.row {
	display: flex;
	align-items: center;
}

Тесты

// user-table.component.test.ts
import { render, screen } from '@testing-library/react';
import { UserTable } from './user-table.component';

describe('UserTable', () => {
    it('renders users', () => {
        const users = [
            { id: 1, name: 'John' },
            { id: 2, name: 'Jane' },
        ];

        render(<UserTable users={users} onEdit={() => {}} />);

        expect(screen.getByText('John')).toBeInTheDocument();
        expect(screen.getByText('Jane')).toBeInTheDocument();
    });
});