Приведи пример задачи Frontend c проекта
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Пример задачи с реального проекта: Реализация динамической таблицы с фильтрацией и сортировкой
На одном из недавних проектов, где мы разрабатывали админ-панель для управления пользователями, передо мной как Frontend Developer стояла задача реализовать таблицу со следующим функционалом:
Требования к задаче
- Отображение списка пользователей (поля: ID, Имя, Email, Дата регистрации, Статус).
- Клиентская пагинация с отображением 10 записей на странице.
- Сортировка по любому столбцу (клик по заголовку).
- Фильтрация по имени и email через текстовое поле ввода.
- Динамическое обновление данных без перезагрузки страницы.
- Высокая производительность при работе с большими наборами данных (1000+ записей).
Технический контекст и мое решение
Проект использовал стек: React 18, TypeScript, TanStack Query (React Query) для управления состоянием серверных данных, и Tailwind CSS для стилей. Для таблицы я выбрал библиотеку TanStack Table (ранее React Table), так как она headless, обеспечивает максимальную гибкость и отличную производительность благодаря виртуализации.
Ключевые шаги реализации:
- Получение и кэширование данных:
Использовал `useQuery` из TanStack Query для загрузки списка пользователей с бэкенда. Это дало встроенный кэш, обработку состояний загрузки и ошибок.
```typescript
import { useQuery } from '@tanstack/react-query';
const fetchUsers = async (): Promise<User[]> => {
const response = await fetch('/api/users');
if (!response.ok) throw new Error('Network error');
return response.json();
};
const UsersTable = () => {
const { data: users = [], isLoading, error } = useQuery({
queryKey: ['users'],
queryFn: fetchUsers,
});
// ... далее логика таблицы
};
```
2. Создание и настройка экземпляра таблицы:
Создал memory-источник данных для клиентской фильтрации и сортировки, используя хуки `useReactTable`.
```typescript
import { useReactTable, getCoreRowModel, getSortedRowModel, getFilteredRowModel, ColumnDef, SortingState } from '@tanstack/react-table';
const [sorting, setSorting] = useState<SortingState>([]);
const [globalFilter, setGlobalFilter] = useState('');
const table = useReactTable({
data: users,
columns, // Массив определений колонок
state: { sorting, globalFilter },
onSortingChange: setSorting,
onGlobalFilterChange: setGlobalFilter,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(), // Для пагинации
});
```
3. Рендеринг UI:
Реализовал компоненты таблицы, инпут для фильтрации и кнопки пагинации, используя данные и методы из экземпляра `table`.
```jsx
return (
<div className="p-4">
{/* Поле глобального фильтра */}
<input
value={globalFilter ?? ''}
onChange={(e) => setGlobalFilter(e.target.value)}
placeholder="Поиск по имени или email..."
className="mb-4 p-2 border rounded"
/>
{/* Сама таблица */}
<table className="min-w-full divide-y divide-gray-200">
<thead>{/* Рендеринг заголовков с кнопками для сортировки */}</thead>
<tbody>
{table.getRowModel().rows.map(row => (
<tr key={row.id}>{/* Рендеринг ячеек для каждой строки */}</tr>
))}
</tbody>
</table>
{/* Элементы управления пагинацией */}
<div className="flex items-center gap-2 mt-4">
<button onClick={() => table.previousPage()} disabled={!table.getCanPreviousPage()}>
Назад
</button>
<span>{`Страница ${table.getState().pagination.pageIndex + 1} из ${table.getPageCount()}`}</span>
<button onClick={() => table.nextPage()} disabled={!table.getCanNextPage()}>
Вперед
</button>
</div>
</div>
);
```
Сложности и их преодоление
- Производительность при фильтрации: Изначальная реализация "в лоб" с фильтрацией массива на каждый ввод символа вызывала подтормаживания. Решение: использовал useMemo для мемоизации отфильтрованных данных и добавил debounce (задержку в 300 мс) на обработчик ввода в фильтр, чтобы уменьшить количество вычислений.
- Типизация: Для строгой типизации данных пользователя и колонок таблицы активно использовал TypeScript Generics, что предотвратило множество потенциальных ошибок на этапе разработки.
- Доступность (a11y): Добавил необходимые ARIA-атрибуты к элементам таблицы и убедился, что вся навигация (сортировка, пагинация) доступна с клавиатуры.
Результат
В результате получился переиспользуемый, производительный и полностью контролируемый компонент таблицы, который успешно интегрировался в несколько разделов админ-панели. Задача была выполнена за 3 спринта (story points: 8), включая код-ревью, написание юнит-тестов (Jest, React Testing Library) и интеграционных тестов (Cypress) для проверки основных пользовательских сценариев (фильтрация, сортировка, пагинация). Компонент стал частью нашей внутренней UI-библиотеки.