@jwhenry/rx-state
TypeScript icon, indicating that this package has built-in type declarations

1.2.3 • Public • Published

RX State

Background

After working with Angular for a few years now, I have come to appreciate how people are able to build Angular specific libraries that accomplish some major feats that make my job easier. I have come to a place where Angular no longer is a part of my best interests and I am trying to find ways to spread some concepts to a framework-agnostic ecosystem that way I don't have to rewrite a majority of application logic just to transfer to a new framework.

As a result of my research and experimentation, I have come to appreciate RXJS in a new way. Due to this new-found appreciation I have come up with a simple state management platform based off of functional programming (slightly) and Redux to compliment those who wish to have a basic-yet-robust state management system without locking into any one framework.

I hope that through my experimentation in this realm that others can benefit from my findings.

That being said, let's get into the meat of the library:

Getting Started

This library is heavily influenced by NGXS and Redux to bring those patterns into a framework-agnostic environment. You should be able to easily throw some code into any framework you want and bind your state and events in any way you please.

To get started: npm i @jwhenry/rx-state --save

Dependencies: rxjs, yes that is all.

Event System

The event system is influenced by pub-sub models, Redux, and NGXS. You are provided a global events constant that you can subscribe to in order to observe actions that take place. You may also set EventOptions.log to true if you wish to watch these actions take place.

The event stream is the source of all state actions or any arbitrary behavior you want to trigger in your application.

An eventsOf function will allow you to provide a list of names or objects with an event property to listen specifically for. When reading about how to create states, you will see how this is used to trigger state mutations within the ecosystem.

Creating States

States act as reducers from Redux or State in NGXS. Their purpose is to handle the state mutation or other dispatching based on the new state values

Example Actions:

export const SomeAction = 'some.action';
export declare type SomePayload = {value:string};
export interface ISomePayload {
    value:string
}
export class StoreSession {
    static readonly event = 'session.store';

    constructor(public data: SessionModel) {

    }
}

export class ClearSession {
    static readonly event = 'session.clear';

}

Example State:

States can be constructed with as little boilerplate as necessary.

  • By using the stateof function, you can build NGXS-like stores with a context to wrap even more boilerplate nicely.
  • You can still access other states by using the selectSnapshot and dispatch functions.
  • The purpose of stateOf is to make your state fully self-aware and self-contained.
import {dispatch, start, stateOf, removeAllStates} from "@jwhenry/rx-state";
import {StoreSession, SessionModel, ClearSession} from "./session-data";
export const SessionState = stateOf<SessionModel>('session', (onEvent, context) => {
    if (!context.getState()) {
        context.setState(new SessionModel()); // Set a default value
    } 
    onEvent(StoreSession, data => {
         // The data will be SessionModel according to the above examples
        context.setState(data);
    });
    onEvent(ClearSession, () => {
        // Clear all states because we don't want to retain anything for users who are not logged in
        removeAllStates();
        // OR remove a specific state
        context.setState(new SessionModel());
    })
}, true); // last argument is whether we persist the state

Observing State

You can observe state in multiple ways:

  • Watch the whole state
    • import {state} from "@jwhenry/rx-state";
      state.subscribe(state => console.log(state));
  • Watch a specific state
    • import {select} from "@jwhenry/rx-state";
      select('session').subscribe(session => console.log(session));
  • Grab a snapshot of a specific state
    • import {selectSnapshot} from "@jwhenry/rx-state";
      console.log(selectSnapshot('session'));

Starting and Stopping States

In order to start your states, you must register them and when ready, start them:

import {register, startStates, stopStates} from "@jwhenry/rx-state";

register(SomeState, SomeOtherState);
startStates();

// Start a state late
start(SomeLazyState);

// After some time or when you want to kill state listeners
stopStates();

Feedback and Future

If there are desired features or feedback that may spark a larger effort on this project, this may become something that developers can use to replace some framework-specific state management tools.

Readme

Keywords

Package Sidebar

Install

npm i @jwhenry/rx-state

Weekly Downloads

2

Version

1.2.3

License

MIT

Unpacked Size

53.5 kB

Total Files

20

Last publish

Collaborators

  • jwhenry123