Разбор кода React приложения: архитектура и советы
В этой статье мы проведём code review учебного проекта на React 19, TypeScript и современном стеке. Разберём ключевые аспекты: разделение ответственности между TanStack Query и Zustand, маршрутизацию, типизацию, валидацию форм и производительность. Вы получите практические рекомендации по улучшению кода.
Архитектура состояния: TanStack Query и Zustand
Архитектура построена грамотно: TanStack Query отвечает за кэширование и синхронизацию данных с API (список пользователей), а Zustand управляет UI-состоянием (скрытые/архивированные карточки). Конфликтов и дублирования нет. Однако есть нюансы:
- Данные из API (первые 6 пользователей) хранятся в кэше TanStack Query. При изменении состояния (архив/скрытие) Zustand обновляет локальный стор. Это верное разделение.
- Рекомендуется синхронизировать Zustand с localStorage через middleware или кастомный хук, чтобы избежать потери данных при перезагрузке. Сейчас это уже реализовано, но стоит проверить, что Zustand не дублирует данные из API.
- Не смешивайте серверное и клиентское состояние в одном сторе - это усложнит отладку. Текущий подход оптимален.
Маршрутизация с React Router v7 Data Router API
Вы используете Data Router API, что даёт преимущества: декларативные loader'ы, предзагрузка данных до рендера. Однако в вашем проекте данные загружаются через TanStack Query внутри компонентов, что тоже корректно. Когда стоит использовать loader'ы?
- Если данные критичны для SEO и первого экрана - loader'ы ускорят загрузку.
- Если данные нужны только после взаимодействия пользователя (клик, сабмит) - TanStack Query внутри компонента гибче.
- В текущем сценарии (список пользователей на главной) loader'ы оправданы: данные можно предзагрузить на этапе маршрутизации, уменьшив количество ререндеров.
Проверьте, что в компонентах нет дублирования запросов: если loader уже загрузил данные, TanStack Query может их перезапросить. Используйте ключи запросов единообразно.
Типизация и TypeScript
Типизация в проекте хорошая, но есть моменты для улучшения:
- Избегайте
any. Если тип API-ответа неизвестен, создайте интерфейс или используйтеunknownс проверкой. - Для пропсов компонентов всегда определяйте интерфейсы (например,
UserCardProps). Это повышает читаемость и автодополнение. - Ипортируйте типы из библиотек (TanStack Query, Zustand) для строгой типизации хуков.
- Для Zod схем используйте вывод типа:
type UserFormData = z.infer.
Работа с формами: React Hook Form + Zod
Связка React Hook Form и Zod - отличный выбор для валидации. Проверьте:
- Обработка ошибок: используйте
formState.errorsи выводите сообщения пользователю. Если ошибка не отображается - проверьте, что схема Zod соответствует полям формы. - Модальное окно при редактировании: синхронизируйте значения формы с данными пользователя через
resetиз React Hook Form. - Валидация на стороне клиента должна дублироваться серверной (если есть API). Zod схемы можно переиспользовать и на бэкенде (если он на Node.js).
Производительность и ререндеры
Чтобы избежать лишних ререндеров:
- Используйте
React.memoдля компонентов, которые часто перерисовываются (например, карточка пользователя). - Хуки
useMemoиuseCallbackприменяйте только для тяжёлых вычислений и колбэков, передаваемых в дочерние компоненты. Не оптимизируйте преждевременно. - Проверьте, что Zustand стор не вызывает ререндер всех подписчиков при изменении одного поля. Используйте селекторы:
const hiddenIds = useUserStore(state => state.hiddenIds). - TanStack Query по умолчанию кэширует данные и минимизирует запросы. Настройте staleTime и cacheTime для оптимальной работы.
Организация кода и best practices
Репозиторий структурирован логично. Рекомендации:
- Разделите компоненты на папки по фичам (features), а не по типам (components, hooks). Это упростит масштабирование.
- Вынесите типы API в отдельный файл
types/api.ts. - Для стилей используйте SCSS Modules - это уже сделано. Хорошо.
- Добавьте ESLint и Prettier для единого стиля кода.
Проект выглядит качественным для обучения. Основные замечания касаются типизации и потенциальной оптимизации ререндеров. Продолжайте практиковаться - стек выбран современный и востребованный.