Nexus State: Современный менеджер состояния для JavaScript-приложений
- понедельник, 16 февраля 2026 г. в 00:00:04
В экосистеме JavaScript-разработки управление состоянием приложений всегда оставалось одной из самых сложных задач. От глобальных переменных до сложных библиотек вроде Redux и MobX — разработчики постоянно ищут более простые и эффективные решения.
Сегодня мы познакомимся с Nexus State — новой библиотекой для управления состоянием, которая сочетает простоту использования Atom-подхода с мощными функциями для реальных приложений. В этой статье мы рассмотрим архитектуру Nexus State, его возможности, и проведем объективное сравнение с существующими решениями.
Nexus State — это легковесная библиотека для управления состоянием, построенная на концепции атомов (atoms). Атомы — это минимальные единицы состояния, которые могут быть:
Примитивными — хранящими простые значения (строки, числа, булевы значения)
Вычисляемыми (computed) — производящими значения на основе других атомов
Асинхронными — управляющими состоянием запросов к API
Ключевые особенности:
✅ Простота и минимализм (менее 2 Кб в gzip)
✅ Built-in DevTools для отладки
✅ Time Travel debugging
✅ Поддержка React, Vue, Svelte и vanilla JS
✅ Плагины для persistence, middleware, async operations и Immer
✅ Автоматическая регистрация атомов для DevTools интеграции
Атом — это минимальная единица состояния. В Nexus State атом создается функцией atom():
import { atom, createStore } from '@nexus-state/core'; // Простой атом с начальным значением const countAtom = atom(0, 'counter'); // Вычисляемый атом на основе другого атома const doubleCountAtom = atom((get) => get(countAtom) * 2, 'doubleCount'); // Создаем store и используем атомы const store = createStore(); console.log(store.get(countAtom)); // 0 store.set(countAtom, 5); console.log(store.get(doubleCountAtom)); // 10
Вычисляемые атомы автоматически пересчитываются при изменении зависимых атомов — без лишних обновлений компонентов.
Store — это контейнер для атомов. Он управляет подписками и обновлениями:
const store = createStore(); // Подписка на изменения const unsubscribe = store.subscribe(countAtom, (value) => { console.log('Count changed:', value); }); // Обновление store.set(countAtom, 10); // Отписка unsubscribe();
import { useAtom } from '@nexus-state/react'; import { atom, createStore } from '@nexus-state/core'; const countAtom = atom(0, 'counter'); const doubleCountAtom = atom((get) => get(countAtom) * 2, 'doubleCount'); function Counter() { const [count, setCount] = useAtom(countAtom); const [doubleCount] = useAtom(doubleCountAtom); return ( <div> <h1>Count: {count}</h1> <p>Double: {doubleCount}</p> <button onClick={() => setCount(count + 1)}>+</button> </div> ); }
Важно: React-компоненты обновляются только когда меняются связанные атомы — никаких лишних ререндеров!
В приведенном ниже примере это можно увидеть в Computed Atoms
import { atom } from '@nexus-state/core'; const [userAtom, fetchUser] = atom.async({ fetchFn: async (store) => { const response = await fetch('/api/user'); return response.json(); } }); // В компоненте const [userState, setUserState] = useAtom(userAtom); // userState содержит: // { loading: boolean, error: Error | null, data: T | null } // Запуск загрузки fetchUser(store);
import { atomFamily } from '@nexus-state/family'; const userAtomFamily = atomFamily((id) => atom({ id, name: '', email: '' }) ); // Получаем атом для конкретного пользователя const user1Atom = userAtomFamily(1); const user2Atom = userAtomFamily(2); store.set(user1Atom, { id: 1, name: 'Alice', email: 'alice@example.com' }); store.set(user2Atom, { id: 2, name: 'Bob', email: 'bob@example.com' });
import { persist, localStorageStorage } from '@nexus-state/persist'; const store = createStore(); // Применяем плагин persistence persist(countAtom, { key: 'count', storage: localStorageStorage })(store); // Теперь значение сохраняется автоматически и восстанавливается при перезагрузке store.set(countAtom, 42); // Обновите страницу — значение останется 42!
import { middleware } from '@nexus-state/middleware'; // Логирование изменений const loggingMiddleware = middleware(countAtom, { beforeSet: (atom, newValue) => { console.log('Will set:', newValue); return newValue; }, afterSet: (atom, newValue) => { console.log('Did set:', newValue); } }); store = createStore([loggingMiddleware]);
import { immerAtom, setImmer } from '@nexus-state/immer'; const userStateAtom = immerAtom({ profile: { name: '', age: 0 }, preferences: { theme: 'light' } }, store); // Обновление вложенных свойств с мутациями setImmer(userStateAtom, (draft) => { draft.profile.name = 'Jane'; draft.preferences.theme = 'dark'; // Draft автоматически становится новым объектом });
Nexus State включает полноценные DevTools, которые позволяют:
🕵️ Inspect все атомы и их значения
⏪ Time Travel — перемотка между состояниями
📊 Просмотр истории изменений
🔄 Восстановление состояния из снапшотов
import { devTools } from '@nexus-state/devtools'; const store = createStore(); const devtoolsPlugin = devTools(); devtoolsPlugin.apply(store);
Критерий | Nexus State | Redux |
|---|---|---|
Синтаксис | Атомы: | Action types, reducers |
Boilerplate | Минимальный | Значительный |
Типизация | Встроенная | Через typescript |
DevTools | Встроены | Redux DevTools extension |
Size | ~2 Кб | ~13 Кб |
Learning curve | Плоская | Крутая |
Computed values | Автоматически | Через selector |
Async | Встроенный asyncAtom | Через middleware (thunk/saga) |
Когда выбрать Redux:
Большие команды, привыкшие к паттерну Redux
Необходимость строгой структуры и конвенций
Исторические причины (множество Redux кода)
Когда выбрать Nexus State:
Желание минимализма и простоты
Нужна быстрая разработка
Требуются вычисляемые значения "из коробки"
Важна интеграция с DevTools
Критерий | Nexus State | Zustand |
|---|---|---|
Парадигма | Атомы | Store функция |
Computed values | Встроены | Через get() |
DevTools | Встроены | Плагин |
Size | ~2 Кб | ~1.5 Кб |
React integration | useAtom | useStore |
Time Travel | Встроен | Не встроен |
Family support | Встроен | Плагин |
Zustand предпочтительнее если:
Нужен самый маленький размер
Используете только React
Не нужен Time Travel
Nexus State предпочтительнее если:
Нужна поддержка Vue/Svelte
Важны DevTools и Time Travel
Требуется family support
Критерий | Nexus State | MobX |
|---|---|---|
Парадигма | Атомы | Observable |
Обновления | Селективные | Автоматические |
Транзакции | Не требуется | Встроены |
DevTools | Встроены | mobx-devtools |
Size | ~2 Кб | ~10 Кб |
Learning curve | Легкая | Средняя |
MobX предпочтительнее если:
Уже используете MobX в проекте
Нужны транзакции "из коробки"
Пре��почтителен observable подход
Nexus State предпочтительнее если:
Нужна более явная модель изменений
Важна интеграция с DevTools и Time Travel
Требуется поддержка нескольких фреймворков
Критерий | Nexus State | Jotai |
|---|---|---|
Архитектура | Store + Atoms | Global atoms |
Store | Встроен | Пользовательский |
Isolation | Хорошая | Через Provider |
DevTools | Встроены | Нужен плагин |
Computed | Встроены | Встроены |
Size | ~2 Кб | ~3 Кб |
Jotai предпочтительнее если:
Нужен глобальный store
Не нужна изоляция
Предпочтителен simpler API
Nexus State предпочтительнее если:
Нужна изоляция ( store)
Важны DevTools и Time Travel
Требуется встроенный persistence
Все атомы автоматически регистрируются в глобальном реестре:
const atomRegistry = { get: (id: symbol) => Atom, getAll: () => Atom[], getName: (atom: Atom) => string }
Это позволяет DevTools отображать все атомы и их зависимости.
Вычисляемые атомы не хранят значение — они вычисляются на лету:
const a = atom(1); const b = atom(2); const c = atom((get) => get(a) + get(b)); // При изменении 'a' или 'b', 'c' автоматически пересчитывается // Компоненты, зависящие от 'c', обновляются только при изменении 'c'
Nexus State автоматически батчит изменения:
store.set(a, 1); store.set(b, 2); // Компоненты обновятся только один раз после всех изменений
Система Time Travel использует снапшоты состояния:
const snapshotManager = new StateSnapshotManager(atomRegistry); const stateRestorer = new StateRestorer(atomRegistry); // Создать снапшот const snapshot = snapshotManager.createSnapshot('USER_ACTION'); // Восстановить состояние stateRestorer.restoreFromSnapshot(snapshot);
Nexus State поддерживает систему плагинов:
import { middleware } from '@nexus-state/middleware'; import { persist } from '@nexus-state/persist'; const store = createStore([ middleware(atom1, { beforeSet: ... }), persist(atom2, { key: 'key', storage: localStorage }), // ... другие плагины ]);
Плагины применяются к store через функции, которые принимают store и расширяют его функциональность.
Использовать вычисляемые атомы для производных данных
Делать атомы достаточно мелкими для точных обновлений
Использовать DevTools для отладки
Применять плагины для side effects (persistence, logging)
Использовать family для списков сущностей
Не хранить в атомах реактивные ссылки на DOM элементы
Не создавать слишком большие атомы (лучше мелкие и независимые)
Не использовать атомы для UI state (фокус, hover и т.д.)
Не забывать отписываться от store при размонтировании
Nexus State оптимизирован для производительности:
Селективные обновления — компоненты обновляются только при изменении связанных атомов
Batched updates — несколько изменений в одной транзакции
Lazy serialization — DevTools сериализует состояние только по запросу
Minimal size — менее 2 Кб без gzip
No overhead in production — DevTools код не включается в production сборку
Nexus State — это современное решение для управления состоянием, которое сочетает минимализм с мощными функциями. Он особенно подходит для:
✅ Новых проектов, где важна простота
✅ Команд, ценящих производительность
✅ Приложений, где важна отладка (DevTools)
✅ Проектов, требующих Time Travel debugging
✅ Микрофронтендов с изоляцией состояния
Библиотека активно развивается и уже демонстрирует отличные результаты в плане производительности и удобства использования.