Привет из магазина MiniRx

MiniRx Store - новый ребенок в блоке управления реактивным состоянием. MiniRx поможет вам управлять состоянием в крупном масштабе (с помощью Redux), но также предлагает простую форму управления состоянием: Магазины функций.

Давайте сделаем краткий обзор:

Глобальный

MiniRx Store - это глобальное решение для всего приложения для управления состоянием в приложениях JavaScript и TypeScript.

Реактивный

MiniRx работает на RxJS и предоставляет состояние как RxJS Observables. Observables испускаются при изменении их выбранного состояния.

Масштабируемый

MiniRx - это полноценное хранилище Redux: оно включает в себя действия, редукторы, мета-редукторы, запоминаемые селекторы и поддержку инструментов разработки redux.
Однако с MiniRx хранилища функций мы можем обойти шаблон Redux: сразу обновить состояние с помощью setState.

MiniRx прекрасно масштабируется в соответствии с вашими требованиями к управлению состоянием:

  • Упростите сложные задачи с помощью Redux API
  • Упростите простые вещи с помощью Feature Store API

Быстрые ссылки

ДНК MiniRx

NgRx

MiniRx вдохновлен NgRx, который является хорошо известным реактивным хранилищем Redux в мире Angular. На первый взгляд MiniRx и NgRx похожи, но есть и важные различия.

Что общего у NgRx и MiniRx?

  • Их имена звучат похоже: попробуйте произнести их вслух;)
  • На платформе RxJS
  • Оба реализуют шаблон Redux.
  • Состояние и действия отображаются как RxJS Observable.

Какие основные отличия?

  • MiniRx не зависит от Angular и не зависит от платформы
  • MiniRx имеет магазины функций для управления состоянием функций без шаблона Redux.
  • MiniRx более легкий и, по общему признанию, не охватывает все безумные варианты использования управления состоянием.

И именно эти различия объясняют название «MiniRx».

Почему MiniRx

NgRx и шаблон Redux хорошо подходят для управления состоянием в большом масштабе. Но почти каждое приложение также содержит функции, требующие лишь простой формы управления состоянием. Тогда шаблон Redux с его действиями и редюсерами быстро становится излишним. Было бы здорово иметь решение для управления состоянием, которое выглядит и по ощущениям очень похоже на NgRx, но также должно поддерживать простое управление состоянием: Масштабируемое управление состоянием. Пришло время создать MiniRx Store:

Обход шаблона Redux с помощью магазинов функций

MiniRx использует шаблон Redux, чтобы сделать управление состоянием явным и предсказуемым. Шаблон Redux очень мощный, но он имеет некоторый шаблонный код (в основном действия, редукторы, действия диспетчеризации). MiniRx позволяет нам обойти шаблон Redux для простых состояний функций: с помощью Магазинов функций мы можем управлять состоянием функции напрямую, без действий и редуктора (просто используйте setState для обновления состояния функции) .

Государственное управление, которое масштабируется

Для простых функций мы можем использовать магазины функций. А магазины функций могут быть довольно мощными: вы можете использовать мемоизированные селекторы (если хотите), вы можете создавать эффекты для вызовов API (если хотите). MiniRx прекрасно масштабируется в соответствии с вашими потребностями.
И вы всегда можете вернуться к Redux API, если вам нужно управлять огромным и сложным состоянием.

Фреймворк агностик

NgRx - отличный реактивный магазин, но в настоящее время он работает только в Angular. Существуют также другие фронтенд-фреймворки, такие как Svelte, которые поддерживают реактивность. Было бы здорово сделать в Svelte управление состоянием в стиле NgRx!
С MiniRx вы можете использовать любую структуру, которую захотите: вы можете создать независимый от платформы уровень управления состоянием для Angular сегодня и переместить его в Svelte (или любую другую структуру внешнего интерфейса) завтра.

Ключевые концепции MiniRx

  • Хранилище - это единый объект, который хранит глобальное состояние приложения. Это «единственный источник истины»
  • Состояние имеет плоскую иерархию и разделено на «состояния функций» (также называемые «срезами» в мире Redux).
  • Для каждого «состояния функции» мы можем решить использовать Redux API с действиями и редуктором или API магазина функций с setState
  • Состояние отображается как RxJS Observable (Хранилище предоставляет глобальное состояние, а Хранилище функций - конкретное состояние функции).
  • Состояние только для чтения (неизменяемое) и может быть изменено только путем отправки действий (Redux API) или с помощью setState (Feature Store API).

Это было долгое вступление! Давайте углубимся в код, чтобы увидеть MiniRx в действии ...

Базовое руководство

Магазин (Redux API)

MiniRx поддерживает классический Redux API с регистрацией редукторов и отправкой действий.
Наблюдаемое состояние можно выбрать с помощью мемоизированных селекторов .

import { Action, Store, configureStore, createFeatureSelector, createSelector } from "mini-rx-store";
import { Observable } from "rxjs";
// 1.) State interface
interface CounterState {
  count: number;
}
// 2.) Initial state
const counterInitialState: CounterState = {
  count: 1
};
// 3.) Reducer
function counterReducer(
  state: CounterState = counterInitialState,
  action: Action
): CounterState {
  switch (action.type) {
    case "inc":
      return {
        ...state,
        count: state.count + 1
      };
    default:
      return state;
  }
}
// 4.) Get hold of the store instance and register root reducers
const store: Store = configureStore({
  reducers: {
    counter: counterReducer
  }
});
// 5.) Create memoized selectors
const getCounterFeatureState = createFeatureSelector<CounterState>("counter");
const getCount = createSelector(
  getCounterFeatureState,
  state => state.count
);
// 6.) Select state as RxJS Observable
const count$: Observable<number> = store.select(getCount);
count$.subscribe(count => console.log("count:", count));
// 7.) Dispatch an action
store.dispatch({ type: "inc" });
// OUTPUT: count: 1
// OUTPUT: count: 2

API магазина функций

Хранилища функций позволяют нам управлять состоянием функций без действий и редукторов.
API магазина функций оптимизирован для выбора и обновления состояния функции напрямую с использованием минимум шаблонов.

import { FeatureStore } from "mini-rx-store";
import { Observable } from "rxjs";
// 1.) State interface
interface CounterState {
  counter: number;
}
// 2.) Initial state
const counterInitialState: CounterState = {
  counter: 11
};
export class CounterFeatureStore extends FeatureStore<CounterState> {
  // Select state as RxJS Observable
  counter$: Observable<number> = this.select(state => state.counter);
  constructor() {
    super("counterFs", counterInitialState)
  }
  // Update state with `setState`
  inc() {
    this.setState(state => ({...state, counter: state.counter + 1}))
  }
}

Используйте хранилище функций counterFs следующим образом:

import { CounterFeatureStore } from "./counter-feature-store";
const counterFs = new CounterFeatureStore();
counterFs.counter$.subscribe(count => console.log("count:", count));
counterFs.inc();
// OUTPUT: count: 11
// OUTPUT: count: 12

Состояние магазина функций становится частью глобального состояния

Каждый новый магазин функций будет отображаться в глобальном состоянии с соответствующим ключом функции (например, «counterFs»):

store.select(state => state).subscribe(console.log);

//OUTPUT: {"counter":{"count":2},"counterFs":{"counter":12}}

Примечания

Демо

🚀 Увидеть MiniRx Store в действии на StackBlitz

В демонстрации используются как Redux API, так и магазины функций:

  • Todos: Магазин функций
  • Продукты и корзина: Redux
  • Пользователь: Магазин функций

Документация

🤓 Ознакомьтесь с документацией для получения полного API MiniRx.

Покажите свою поддержку

Если вам нравится MiniRx: поставьте на GitHub

использованная литература

Эти проекты, статьи и курсы помогли и вдохновили меня на создание MiniRx:

Первоначально опубликовано на https://dev.to 26 февраля 2021 г.