npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

rx-simple-store

v0.3.0

Published

A simple rx store solution written in TypeScript

Downloads

25

Readme

Build Status

rx-simple-store

This is an isomorphic distributed rxjs 5 implementation of a reactive store, written in TypeScript.

History

I was originally inspired by the article Redux in a single line of code with RxJS by Rudi Yardley.

Then I switched to a more mobx-like implementation. I liked the idea of having actions as simple methods on the store.

So in version 0.2.0 I did a rewrite: Instead of working with actions as objects like in redux, we now add actions as methods to our store implementations.

Why another store solution?

At the moment I write some applications in Angular and React.

  • There is the @ngrx/store or redux which allows you to have a centralized application state.

    This is a nice solution for a lot of applications. With the great redux dev tools, you can keep track of your actions.

  • On the other hand there is mobx which is a distributed store and works with it's own observable implementation.

Advantages

  • In @ngrx/store and redux you have to create a lot of boilerplate code to finally get your store set-up and you have to jump through a lot of files when you want to change a behavior.

    With the RxStore you have everything from the actions to to the state within one file (like in mobx).

  • Mobx is larger than this small library and it has it's own observable implementation which is unlikely to be reused by a library consumer.

    Since this library uses rxjs, it has a very small size (it's only one class). And rxjs is very light, too (when you include only the operators you need into your application). If you use Angular, you have rxjs as an implicit dependency anyways.

Drawbacks

  • Hot-Module-Reloading might be easier to be implemented with a central store solution.
  • @ngrx/store and redux have an action history log and you can simply modify it with the dev tools to get a different resulting state. This is not a feature of mobx or this store.

API

RxStore

constructor

Creates a new store instance.

new RxStore<S>(initialState: S, options?: RxStoreOptions);

RxStore.prototype.state

This is a reference to the current state snapshot.

RxStore.prototype.state$

The state$ is a rxjs Observable<S>. Here you can subscribe for state updates.

RxStore.prototype.publish(patch: Partial<S>) (protected)

This is an internal method that can be used by your store actions to publish state changes.

RxStoreOptions

debug?: boolean

Determines whether the the state changes of the store are logged to the console.

mutateState?: boolean

Determines whether the state should be mutated when calling publish.

A Todo Example

import { RxStore } from "rx-simple-store";

interface Todo {
  text: string;
  done: boolean;
}

interface TodoState {
  todos: Todo[];
}

class TodoStore extends RxStore<TodoState> {
  addTodo(todo: Todo) {
    this.publish({
      todos: [...this.state.todos, todo],
    });
  }

  updateTodo(idx: number, todo: Partial<Todo>) {
    const todos = this.state.todos;
    this.publish({
      todos: [
        ...todos.slice(0, idx),
        Object.assign(todos[idx], todo),
        ...todos.slice(idx + 1),
      ],
    });
  }
}

const todoStore = new TodoStore({ todos: [] });

todoStore.addTodo({ text: "Read the docs", done: false });
todoStore.updateTodo(0, { done: true });
todoStore.addTodo({ text: "Use it", done: false });
todoStore.updateTodo(1, { text: "Apply it" });

// state:
// ​​​​​{​​​​​
// ​​​​​  "todos": [​​​​​
// ​​​​​    {​​​​​
// ​​​​​      "text": "Read the docs",​​​​​
// ​​​​​      "done": true​​​​​
// ​​​​​    },​​​​​
// ​​​​​    {​​​​​
// ​​​​​      "text": "Apply it",​​​​​
// ​​​​​      "done": false​​​​​
// ​​​​​    }​
// ​​​​​  ]​​​​​
// ​​​​​}​​​

Usage with angular

In angular you can simply subclass the RxStore and inject it to your components.

Example

Store (similar to example above):

// ...

@Injectable()
export class TodoStore extends RxStore<TodoState> {
  // ...
}

Component:

@Component({
  // ...
})
export class TodosComponent {
  todos$ = this.todoStore.state$.map(state => state.todos);

  constructor(public todoStore: TodoStore) {
  }
}

Usage with react, inferno or preact

If you use react or a react-like library, you can connect a stateful component to a store by using the connect decorator.

Example:

import { connect } from "rx-simple-store";

interface State {
  todos: TodoState;
}

@connect({ todos: todoStore })
export class Todos extends Component<{}, State> {
  render() {
    const todos = this.state.todos;
    return (
      <ul>
        {todos.todos.map(todo => (<li>{todo.text}</li>))}
      </ul>
    );
  }
}