3.1 KiB
UI Pattern
Формы используют react-hook-form, zodResolver и FormProvider. Form state создаётся в контейнере или VM, чистое представление получает onSubmit и disabled, а поля подключает через useFormContext.
Во время submit все действия формы блокируются. Ошибки Zod отображаются у поля; ошибки сети сохраняют введённые значения и показываются отдельным Alert.
Запросные экраны без успешных данных выбирают состояние в порядке loading, error, empty, loaded. Если query уже содержит данные, они остаются видимыми при фоновом refetch и его ошибке: рядом показываются неблокирующий progress и локальное предупреждение с retry. Такое состояние называется Client Cached Snapshot; оно не заменяет доменное server-side stale/fallback состояние.
Для finance-экранов используется граница container -> ViewModel -> view.
*.tsx без суффикса — container: он вызывает единственный page VM hook и
выбирает top-level Loading/Error/Empty/Loaded view. *.vm.ts владеет data
fetching, auth/route inputs, state selection, retry callbacks, domain grouping
и derived presentation data. *.view.tsx и соседние presentation components
получают props и рендерят JSX.
View modules не вызывают data/auth/router/navigation/VM hooks: никаких
useBrokerage*, usePortfolio, useAuth, useParams, useNavigate или
page VM hooks внутри *.view.tsx и components/*.view.tsx. View modules также
не группируют domain collections и не считают derived collection values вроде
долей Portfolio Position. Эти значения готовит VM.
Допустимые hooks во view: useTranslation() для labels, form-context hooks в
form views и локальный UI-only state для rendering fallback, например failed
image state. Простое форматирование одного переданного значения через
существующий formatter остаётся presentation concern; вычисления из всей
коллекции остаются во VM.
View files дробятся по смысловой нагрузке, а не только по количеству строк. Если
section или state имеет самостоятельный смысл и может быть назван, его нужно
выносить в nearby presentation component вместо накопления внутри одного
большого *.view.tsx.
Known API errors, retry и stale snapshot остаются local views, а непойманные route errors обрабатывает общий route-keyed ErrorBoundary.