Диспетчеризация действий

В основе Kepler.gl лежит архитектура управления состоянием, построенная вокруг Redux-подобного потока данных, где центральную роль играет диспетчеризация действий (dispatch). Все изменения визуализации, загрузка данных, конфигурация слоёв, фильтров и интерактивных элементов проходят через единый механизм action → reducer → state.

Kepler.gl структурирует состояние в несколько ключевых доменов: visState, mapState, uiState, mapStyle. Каждый из них обновляется исключительно через действия, поступающие в store, что обеспечивает предсказуемость поведения и воспроизводимость визуализаций.

Диспетчеризация в Kepler.gl не является второстепенной деталью реализации — она формирует основной контракт между пользовательским интерфейсом, данными и визуальным движком deck.gl.


Базовый поток действий

Любое изменение в приложении Kepler.gl проходит через единый цикл:

  1. Создание action creator’а
  2. Формирование action-объекта
  3. Вызов dispatch(action)
  4. Обработка reducer’ами
  5. Обновление состояния store
  6. Перерендер визуализации

Каждое действие представляет собой объект с обязательным полем type и дополнительным payload, зависящим от конкретной операции.

Пример логики:

  • загрузка данных → addDataToMap
  • изменение слоя → layerConfigChange
  • фильтрация → filterUpdate
  • переключение UI → toggleModal

Структура action-объекта

Действия Kepler.gl следуют стандартному контракту Redux:

{
  type: 'ACTION_TYPE',
  payload: { ...данные },
  meta: { ...служебная информация }
}

Однако в Kepler.gl часто используется более богатая структура payload, включающая:

  • набор датасетов
  • конфигурации слоёв
  • параметры фильтров
  • стили карты
  • временные метки взаимодействий

Пример добавления данных:

dispatch(addDataToMap({
  datasets: {
    info: {
      label: 'dataset',
      id: 'sample_data'
    },
    data: geojsonData
  },
  options: {
    centerMap: true,
    readOnly: false
  }
}));

Типы действий в Kepler.gl

Диспетчеризация охватывает несколько категорий действий, каждая из которых воздействует на определённый слой состояния.

Действия работы с данными

  • addDataToMap
  • removeDataset
  • updateTableColor
  • setFilter

Эти действия инициируют загрузку, удаление и трансформацию геоданных. Они напрямую влияют на visState.datasets.


Действия управления визуализацией

  • layerConfigChange
  • layerTypeChange
  • toggleLayer
  • reorderLayer

Эти действия изменяют параметры deck.gl слоёв, включая их типы, стили и порядок отрисовки.


Действия фильтрации

Фильтрация реализована через отдельный сегмент состояния:

  • filterUpdate
  • addFilter
  • removeFilter
  • animationConfigChange

Каждое действие модифицирует набор фильтров, применяемых к данным перед визуализацией.


Действия UI

  • toggleSidePanel
  • updateMapControl
  • showModal
  • hideModal

UI-диспетчеризация отделена от визуальных данных, но может влиять на отображение слоёв и конфигураций.


Поток dispatch в Kepler.gl

Центральная точка диспетчеризации — Redux store, переданный через провайдер или HOC KeplerGl.

Каждый action проходит следующий путь:

  1. Компонент вызывает action creator

  2. Action передаётся в dispatch

  3. Middleware (если подключены) перехватывают действие

  4. Root reducer делегирует обработку подредьюсерам:

    • visStateReducer
    • mapStateReducer
    • uiStateReducer
  5. Новый state возвращается в store

  6. React-компоненты получают обновление через connect

Особенность Kepler.gl заключается в том, что часть логики обработки данных выполняется до попадания в reducer, в специализированных утилитах трансформации данных.


Action creators Kepler.gl

Kepler.gl предоставляет набор встроенных action creators, инкапсулирующих структуру действий.

Примеры:

import KeplerGl from 'kepler.gl';
import { addDataToMap, updateMap } from 'kepler.gl/actions';

addDataToMap

Основной механизм загрузки данных и их первичной инициализации:

  • парсинг dataset
  • создание layer configs
  • инициализация фильтров
  • центрирование карты (опционально)

updateMap

Используется для массового обновления состояния карты:

  • изменение viewport
  • синхронизация взаимодействий
  • обновление стиля

layerConfigChange

Действие тонкой настройки слоя:

  • изменение цвета
  • изменение агрегации
  • настройка отображения

Связь dispatch с visState

visState является наиболее чувствительным к действиям сегментом состояния.

Любое действие, связанное с визуализацией, проходит через строгую цепочку:

  • action → visState reducer → recalculation layers → recompute filters → update deck.gl layers

Особенность Kepler.gl заключается в том, что изменения visState могут инициировать каскадные обновления, включая пересборку геометрии и перерасчёт агрегаций.


Middleware и расширение диспетчеризации

Kepler.gl допускает использование middleware между dispatch и reducer. Это позволяет:

  • логировать действия
  • модифицировать payload
  • синхронизировать состояние с внешними источниками
  • интегрировать аналитику

Пример middleware-потока:

const loggerMiddleware = store => next => action => {
  console.log(action.type);
  return next(action);
};

Middleware особенно важны при работе с потоковыми данными или внешними API, где требуется контроль последовательности dispatch.


Асинхронная диспетчеризация

Несмотря на синхронную природу Redux reducer’ов, Kepler.gl поддерживает асинхронные действия через thunk-подобные механизмы.

Пример:

  • загрузка данных с сервера
  • парсинг больших GeoJSON файлов
  • обработка CSV перед dispatch
dispatch(async (dispatch) => {
  const data = await fetch(url).then(r => r.json());
  dispatch(addDataToMap({ datasets: data }));
});

Асинхронный слой часто используется при интеграции с внешними источниками геоданных.


Кастомные действия и расширение системы

Kepler.gl допускает внедрение пользовательских action types, которые обрабатываются расширенными reducer’ами.

Применение:

  • добавление новых типов слоёв
  • кастомные фильтры
  • интеграция с бизнес-логикой

Пример структуры:

const CUSTOM_ACTION = 'CUSTOM_ACTION';

function customAction(payload) {
  return {
    type: CUSTOM_ACTION,
    payload
  };
}

Для корректной работы требуется расширение root reducer и подключение дополнительной логики обработки.


Взаимодействие dispatch с React-интеграцией

Kepler.gl обычно используется через React-компонент:

<KeplerGl
  id="map"
  width={width}
  height={height}
  mapboxApiAccessToken={token}
/>

Компонент подключается к Redux store и автоматически получает доступ к dispatch. Любые действия из интерфейса (перетаскивание слоёв, изменение фильтров) транслируются в dispatch-события.

Связка реализуется через connect:

  • mapStateToProps → доступ к visState
  • mapDispatchToProps → action creators

Поток сложных действий

Некоторые действия в Kepler.gl являются композиционными. Например, addDataToMap инициирует сразу несколько внутренних dispatch:

  • создание dataset
  • генерация слоя
  • инициализация фильтров
  • обновление viewport

Это превращает одно действие в цепочку внутренних событий, что важно учитывать при отладке и профилировании.


Ошибки диспетчеризации и диагностика

Типовые проблемы в системе dispatch:

  • несоответствие структуры payload
  • некорректный dataset format
  • потеря синхронизации visState и mapState
  • конфликт middleware
  • повторная диспетчеризация одного и того же action

Диагностика осуществляется через:

  • Redux DevTools
  • логирование middleware
  • анализ последовательности action.type
  • проверку immutability состояния

Особое внимание требуется при работе с большими геоданными, где один dispatch может приводить к значительной нагрузке на перерасчёт слоёв.


Поведенческая модель диспетчеризации

Kepler.gl следует принципу строгой однонаправленной архитектуры, где:

  • состояние не изменяется напрямую
  • все изменения проходят через dispatch
  • визуализация полностью определяется состоянием
  • действия являются единственным источником изменений

Такой подход обеспечивает детерминированность и масштабируемость при работе с геопространственными данными и интерактивными картами.