Code Monkey home page Code Monkey logo

mini-rx-store's Introduction

MiniRx - RxJS Redux Store - Logo

NPM semantic-release MIT License Tests All Contributors Downloads styled with prettier

New Blogpost: MiniRx Signal Store for Angular - API Preview

New Discussion: Angular Signal Store RFC

MiniRx Store 5

MiniRx Store 5 has been released (2023-04-17)!

What's new?

  • Component Store:
    • Manage state independently of the global state object (which is used by Store and Feature Store)
    • Component Store and Feature Store share the same API (setState, select, effect...)
    • Component Store is perfect for managing smaller and local state (most times that is Component state)
    • You can use most of the MiniRx extensions: Logger Extension, Undo Extension and Immutable Extension
    • Extensions can be configured globally or individually for each Component Store instance
  • Tree-shakable: even more lightweight!
  • Lazy state initialisation with setInitialState
  • setState accepts also an Observable: use an Observable to update state
  • createFeatureSelector has been deprecated. Use now createFeatureStateSelector which is more in line with createComponentStateSelector

Read more in the CHANGELOG about the changes and the very few BREAKING CHANGES.

Angular Integration (mini-rx-store-ng)

  • ComponentStoreModule: Configure ComponentStore extensions globally with the forRoot static method
  • BREAKING CHANGE: StoreDevtoolsModule has been removed. You can use now the normal ReduxDevtoolsExtension from mini-rx-store with StoreModule.forRoot.

Read more in the CHANGELOG of the Angular Integration.

Installation

npm i mini-rx-store

Install the Angular Integration if you are using Angular:

npm i mini-rx-store-ng

The Angular Integration requires now Angular@12.

MiniRx Store

MiniRx Store provides Reactive State Management, powered by RxJS. It is a highly flexible solution and scales with your state management needs:

  • Manage global state at large scale with the Store (Redux) API
  • Manage global state with a minimum of boilerplate using Feature Stores
  • Manage local component state with Component Stores

MiniRx always tries to find the sweet spot between powerful, simple and lightweight.

๐Ÿค“ Learn more about MiniRx on the docs site

๐Ÿš€ See MiniRx in action:

What's Included

  • RxJS powered global state management
  • State and actions are exposed as RxJS Observables
  • Store (Redux):
    • Actions
    • Reducers
    • Meta Reducers
    • Memoized Selectors
    • Effects
    • mapResponse operator: handle the side effect response in Effects
    • Support for ts-action: Create actions and reducers more efficiently
  • Feature Store: Manage feature state directly with a minimum of boilerplate:
    • setState() update the feature state
    • setInitialState() initialize state lazily
    • select() select state from the feature state object as RxJS Observable
    • effect() run side effects like API calls and update feature state
    • undo() easily undo setState actions (requires the UndoExtension)
    • destroy() remove the feature state from the global state object
    • tapResponse operator: handle the side effect response in Feature Store effect
  • Component Store: Manage state locally:
    • Component Store is perfect for local component state
    • Component Store has the same simple API as Feature Store (setState, select, ...)
    • Component Store state is independent of the global state object
    • Component Store is destroyable
  • Extensions:
    • Redux DevTools Extension: Inspect global state with the Redux DevTools
    • Immutable Extension: Enforce state immutability
    • Undo Extension: Undo dispatched actions
    • Logger Extension: console.log the current action and updated state
  • Framework-agnostic: MiniRx works with any frontend project built with JavaScript or TypeScript (Angular, Svelte, React, Vue, or anything else)
  • TypeScript support: The MiniRx API comes with TypeScript type definitions
  • Angular Integration: Use MiniRx Store the Angular way:
    • Configure the Store with StoreModule.forRoot()
    • Add feature state with StoreModule.forFeature()
    • Inject Store and Actions

Key Concepts

  • State and actions are exposed as RxJS Observables
  • Single source of truth: The Store holds a single object which represents the global application state
  • The global state has a flat hierarchy and is divided into "feature states" (also called "slices" in Redux world)
  • For each "feature state" we can decide to use the Store (Redux) API with actions and reducers or the simplified FeatureStore API
  • Store and FeatureStore are different APIs for one and the same Redux Store
  • Use ComponentStore to manage state which is independent of the global state object
  • State is read-only (immutable) and can only be changed by dispatching actions (Redux API) or by using setState (Feature Store / Component Store)

Installation

Install from the NPM repository using npm:

npm install mini-rx-store

Install the RxJS peer dependency:

npm install rxjs

Basic Tutorial

Let's dive into some code to see MiniRx in action. You can play with the tutorial code on StackBlitz.

Store (Redux)

MiniRx supports the classic Redux API with registering reducers and dispatching actions. Observable state can be selected with memoized selectors.

import {
  Action,
  Store,
  configureStore,
  createFeatureStateSelector,
  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 = createFeatureStateSelector<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));
// OUTPUT: count: 1

// 7.) Dispatch an action
store.dispatch({ type: 'inc' });
// OUTPUT: count: 2

Read more in the MiniRx docs: Store (Redux)

Feature Store

With MiniRx Feature Stores we can manage feature state directly with a minimum of boilerplate.

import { FeatureStore } from 'mini-rx-store';
import { Observable } from 'rxjs';

// State interface
interface CounterState {
  count: number;
}

// Initial state
const counterInitialState: CounterState = {
  count: 11
};

// Extend FeatureStore and pass the State interface
export class CounterFeatureStore extends FeatureStore<CounterState> {
  // Select state as RxJS Observable
  count$: Observable<number> = this.select(state => state.count);

  constructor() {
    // Call super with the feature key and the initial state
    super('counterFs', counterInitialState);
  }

  // Update state with `setState`
  inc() {
    this.setState(state => ({ count: state.count + 1 }));
  }
}

Use the "CounterFeatureStore" like this:

import { CounterFeatureStore } from "./counter-feature-store";

const counterFs = new CounterFeatureStore();
counterFs.count$.subscribe(count => console.log('count:', count));
// OUTPUT: count: 11

counterFs.inc();
// OUTPUT: count: 12

โ„น๏ธ The state of a Feature Store becomes part of the global state

Every new Feature Store will show up in the global state with the corresponding feature key (e.g. 'counterFs'):

store.select(state => state).subscribe(console.log);
// OUTPUT: {"counter":{"count":2},"counterFs":{"count":12}}

Read more in the MiniRx docs: Feature Store

Component Store

Manage state locally and independently of the global state object. Component Store has the identical API as Feature Store.

import { ComponentStore } from 'mini-rx-store';
import { Observable } from 'rxjs';

// State interface
interface CounterState {
  count: number;
}

// Initial state
const counterInitialState: CounterState = {
  count: 111,
};

// Extend ComponentStore and pass the State interface
export class CounterComponentStore extends ComponentStore<CounterState> {
  // Select state as RxJS Observable
  count$: Observable<number> = this.select((state) => state.count);

  constructor() {
    // Call super with the initial state
    super(counterInitialState);
  }

  // Update state with `setState`
  inc() {
    this.setState((state) => ({ count: state.count + 1 }));
  }
}

Use the "CounterComponentStore" like this:

const counterCs = new CounterComponentStore();
counterCs.count$.subscribe(count => console.log('count:', count));
// OUTPUT: count: 111

counterCs.inc();
// OUTPUT: count: 112

Read more in the MiniRx docs: Component Store

See the basic tutorial on StackBlitz: MiniRx Store - Basic Tutorial

Demos and examples:

Demos:

These popular Angular demo applications show the power of MiniRx:

More about MiniRx:

Blog Posts:

Community

References

These projects, articles and courses helped and inspired us to create MiniRx:

License

MIT

Contributors โœจ

Thanks goes to these wonderful people (emoji key):

Pieter Van Poyer
Pieter Van Poyer

๐Ÿ’ป
Florian Spier
Florian Spier

๐Ÿ’ป ๐Ÿค”
Carsten
Carsten

๐ŸŽจ
Maximo Cudich-Sieburger
Maximo Cudich-Sieburger

๐Ÿ’ป
sashion
sashion

๐Ÿ’ป
BrainCrumbz
BrainCrumbz

๐Ÿ’ป
vangenechtenbert
vangenechtenbert

๐Ÿ‘€
mvmiert
mvmiert

๐Ÿ‘€

This project follows the all-contributors specification. Contributions of any kind welcome!

mini-rx-store's People

Contributors

allcontributors[bot] avatar dependabot[bot] avatar giuseppepiscopo avatar m5150 avatar mini-rx avatar pietervanpoyer avatar portofantwerp avatar sashion avatar spierala avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.