Reducers в Kepler.gl построены поверх архитектуры Redux и определяют единственный механизм изменения состояния приложения. Вся модель данных библиотеки сводится к иммутабельным преобразованиям, где каждый редьюсер отвечает за строго ограниченный фрагмент глобального состояния: карты, слоёв, датасетов и интерфейса. Такая организация обеспечивает предсказуемость обновлений и упрощает интеграцию с внешними источниками данных и кастомными расширениями.
Внутренняя структура Kepler.gl основана на разделении состояния на несколько доменов:
Каждый из этих сегментов обслуживается отдельным reducer-ом, а
итоговый root reducer собирается через combineReducers. Это
позволяет изолировать логику изменения состояния и минимизировать
побочные эффекты.
Reducers Kepler.gl строго придерживаются принципа неизменяемости. Вместо модификации существующих объектов создаются новые структуры данных:
map, filter,
concatТакой подход критичен для корректной работы селекторов и оптимизации рендеринга, поскольку позволяет быстро определять изменения через shallow comparison.
visState является наиболее сложным сегментом состояния. Он управляет визуализацией данных и включает:
Reducer visState обрабатывает широкий набор action-ов:
Каждое действие преобразуется в новый объект состояния, при этом структура слоёв пересобирается частично или полностью в зависимости от глубины изменений.
При изменении параметров слоя (например, радиуса точек) reducer выполняет:
Ключевая особенность заключается в том, что даже минимальное изменение приводит к новой ссылке на массив layers, что гарантирует корректное обновление UI.
mapState отвечает за географическое положение и камеру визуализации:
Reducer mapState работает с действиями перемещения карты и изменением viewport. Важным аспектом является синхронизация с внешними библиотеками картографии, такими как Mapbox GL, где состояние камеры должно обновляться атомарно.
Особенность реализации заключается в том, что mapState часто обновляется с высокой частотой (например, при панорамировании), поэтому reducer оптимизирован для минимального количества аллокаций объектов.
uiState содержит состояние пользовательского интерфейса:
Reducer uiState отличается более простой структурой по сравнению с visState, но включает множество булевых флагов и строковых идентификаторов. Основная задача — обеспечить синхронизацию UI с текущим режимом работы карты без вмешательства в данные визуализации.
mapStyle управляет визуальным стилем карты:
Reducer обновляет конфигурацию стиля через замену объектов style и styleType. При этом часто используется механизм глубокого клонирования, поскольку стили могут содержать вложенные JSON-структуры.
datasets reducer отвечает за загрузку, хранение и обновление источников данных. Каждый dataset включает:
Reducer обрабатывает:
Особенность заключается в тесной связи с visState: изменения данных часто триггерят перерасчёт слоёв и фильтров.
Все reducers объединяются в единый root reducer:
Такой подход обеспечивает модульность и позволяет расширять систему без изменения базовой логики. Каждый reducer работает в своей области ответственности и не зависит напрямую от других, взаимодействие происходит только через actions.
Actions в Kepler.gl представляют собой описания событий:
Reducer принимает action и проверяет его тип. В зависимости от типа
выполняется соответствующая трансформация состояния. Внутренне
используется pattern switch(action.type).
При этом часть логики вынесена в утилиты и helpers, чтобы reducers оставались максимально чистыми и предсказуемыми.
Для работы с глубоко вложенными структурами Kepler.gl использует вспомогательные функции:
Это позволяет избежать прямого мутационного кода и сохранять совместимость с Redux DevTools.
Оптимизация reducers достигается за счёт:
Reducers формируют состояние, которое затем используется селекторами для вычислений. Селекторы извлекают:
Благодаря иммутабельной природе reducers, селекторы могут эффективно определять изменения и избегать лишних перерасчётов.
Kepler.gl допускает расширение reducers через middleware и custom enhancers. Возможны сценарии:
Кастомный reducer может быть объединён с базовыми через
combineReducers, сохраняя совместимость с ядром
библиотеки.
Типичный цикл работы reducers выглядит следующим образом:
Каждый этап строго детерминирован и не содержит скрытых побочных эффектов, что обеспечивает стабильность визуализации.
Разделение состояния на независимые reducers позволяет:
Такое устройство особенно важно для геопространственных приложений, где одновременно обрабатываются десятки тысяч объектов и множество слоёв визуализации.