Skip to content
Isaak-ossPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Управление картографическими слоями

React + TypeScript + vedro + Vite.

Температура, ветер и инсоляция: включение и выключение, регулировка прозрачности, статус загрузки и повторная попытка после ошибки. Интерфейс — простая таблица без карты.

Запуск

Нужен Node.js 22.12+.

npm ci
npm run dev

Сборка: npm run build. Просмотр сборки: npm run preview.

Архитектура

Проект организован по FSD:

  • app — подключение Vedro Provider и стили.
  • pages — экран приложения.
  • widgets/layers-panel — таблица и строки.
  • features/manage-layer — управление загрузкой и прозрачностью.
  • entities/map-layer — типы, конфигурация, store и mock API.

LayersPanel создаёт строки из конфигурации. LayerRow отвечает только за разметку и передаёт детям id и имя слоя, не подписываясь на store. Каждый компонент находится в отдельном файле.

LayerLoadingControl объединяет checkbox и повторную загрузку. LayerOpacity отвечает за ползунок и процент прозрачности, LayerStatus — за статус запроса. Асинхронная логика находится в hook useLayerLoading, обновления состояния — в helpers сущности.

Управление состоянием в vedro

Все слои хранятся в одном store, созданном через createVedro<LayersStore>. В корне приложения подключён один Vedro Provider, дополнительных Context и провайдеров отдельных слоёв нет.

type Layer = LayerDefinition & LayerState
type LayersStore = Record<LayerId, Layer>

Ключи store — id слоёв (temperature, wind, insolation). Значение содержит описание слоя, enabled, opacity и resource. Начальное состояние создаётся из конфигурации; повторяющиеся id вызывают ошибку.

Helpers используют store.get и store.dispatch. При обновлении заменяется только нужный слой, остальные сохраняют ссылки. Прозрачность ограничена диапазоном 0–1; запись прежнего значения не вызывает dispatch. Статусы и ошибки хранятся в vedro, без дублирования в локальном React state.

Асинхронность и race condition

useLayerLoading управляет запросом одного слоя. Checkbox и retry используют один экземпляр hook и общий AbortController, сохранённый в useRef.

  • При включении слой сразу получает enabled: true и статус loading.
  • При выключении ссылка на текущий запрос обнуляется до вызова abort, а статус сбрасывается в idle. Прозрачность сохраняется.
  • Новый запрос отменяет предыдущий. После await результат записывается только при совпадении controller с текущим и если слой ещё включён.
  • Такая же проверка применяется к ошибкам. Старый finally не может очистить controller нового запроса.
  • Retry разрешён только для включённого слоя в статусе error. При размонтировании компонент отменяет запрос и выключает слой.

При быстром переключении «включить → выключить → включить» ответ первого запроса не меняет состояние второго. Отмена останавливает ненужную работу, а проверка идентичности защищает даже от транспорта, который проигнорировал AbortSignal.

После загрузки обновляется только resource из актуального состояния store: изменение прозрачности во время запроса не откатывается.

Mock имитирует задержку API. Первый завершённый запрос ветра возвращает ошибку, повторная попытка — успех.

Строгая типизация

В исходниках нет any, все типы описаны через type. В TypeScript включены strict, noUncheckedIndexedAccess и exactOptionalPropertyTypes.

LayerResource — объединение вариантов idle, loading, success и error. Поле message доступно только после проверки status === 'error'. Поля состояния объявлены readonly и обновляются иммутабельно.

API имеет сигнатуру LoadLayer: принимает описание слоя и AbortSignal, возвращает Promise<void>. Пойманные ошибки имеют тип unknown; сообщение извлекается после проверки instanceof Error.

Рендеринг

Дочерние компоненты используют встроенный useSelector vedro, экспортированный как useLayersSelector:

  • LayerLoadingControl выбирает enabled и сообщение ошибки одним селектором.
  • LayerOpacity выбирает только opacity.
  • LayerStatus выбирает только status.

Изменение opacity вызывает обновление ползунка, но не строки, переключателя, статусов или соседних слоёв. LayerRow и список не подписаны на store.

Компоненты обёрнуты в memo, чтобы пропускать рендеры родителя с прежними props. Обработчики checkbox и retry стабильны благодаря useCallback, поэтому не нарушают мемоизацию дочерних компонентов.

В установленной версии vedro селекторы пересчитываются при каждом обновлении общего store, а результаты сравниваются через JSON.stringify. Пересчёт селектора не означает перерендер: компонент обновляется, когда выбранное значение изменилось. Id компонентов постоянны благодаря key={id}, что важно для hook библиотеки, сохраняющего первоначальный селектор.

Масштабирование

Переход с 5 к 100+ слоям не требует изменения компонентов: слои добавляются в конфигурацию. Обновление состояния одного слоя не вызывает полную перерисовку списка — обновляются компоненты с изменившимися выбранными значениями. Это можно проверить, временно добавив console.log('rerender') в тела компонентов и изменяя прозрачность или включённость слоя. В development StrictMode возможны дополнительные вызовы рендера.

При необходимости список можно оптимизировать виртуализацией или пагинацией. При этом нужно учитывать текущее поведение: размонтирование компонента выключает слой и отменяет его запрос. Для сохранения активных слоёв при скрытии строк управление запросами потребуется отделить от их жизненного цикла.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages