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

redux-elements

v1.12.3

Published

Opinionated framework for redux state elements

Downloads

136

Readme

Redux-elements

Redux-elements is an opinionated framework for holding normalized, log-based state in redux. It comes with the following features:

  • Automatically defined actions to update the data
  • Automatically defined auto-caching selectors based on reselect
  • Can automatically sync with an API module
  • Supports roll-back and "time travel" of actions, efficiently recalculating store state

Redux-elements uses immutable.js, reselect and redux-saga. It is compatible with react-redux.

Docs

Check out the documentation pages.

Installation

You can install this repository via npm.

npm i redux-elements

Automatically defined actions

No need to endlessly redefine simple CRUD actions.

Redux-elements supports the following actions out of the box:

  • add: Adds one or more items to the data
  • set: Wipes existing data and replaces it with one or more elements
  • clear: Wipes existing data, resets this element to initial (empty) state
  • update: Updates one or more rows in the data
  • upsert: Update or create one or more rows in the data
  • patch: Update select columns of one or more rows in the data
  • delete: Delete one or more rows in the data

Example:

const Session = new StateElement("session","");
const User = new StateElement("user","");
const store = createStore(combineReducers({
  sessions: Session.reducer,
  users: User.reducer
}));
store.dispatch(
  Session.changeState.set([
    {
      id: "sid1",
      userId: "uid1"
    },
    {
      id: "sid2",
      userId: "uid1"
    }
  ])
);
store.dispatch(
  Session.changeState.upsert([
    {
      id: "sid3",
      userId: "uid3"
    },
    {
      id: "sid2",
      userId: "newUserId"
    }
  ])
)
store.getState()
/* {
  sessions: [
    {
      id: "sid1",
      userId: "uid1"
    },
    {
      id: "sid2",
      userId: "newUserId"
    },
    {
      id: "sid3",
      userId: "uid3"
    }
  ],
  users: []
  }
 *

Auto-caching selectors

Redux-elements automatically exposes chainable, optimally caching selectors, supporting database-style joins.

Example:

User.select("duplicateNames")
  .fromState(state)
  .keyBy("firstName") // autocaching
  .filter(listOfUsers => listOfUsers.length>=2, 2) // caching by parameter `2`
  .map(listOfUsers => listOfUsers.first(), "first")  // caching by parameter `"first"`

User.select("duplicateNames")
  .fromState(state)
  .keyBy("firstName") // uses cached result
  .filter(listOfUsers => listOfUsers.length>=2, 2) // uses cached result
  .map(listOfUsers => listOfUsers.last(), "last")  // calculated since caching parameters not equal

See documentation for more details.

Roll-back and time-travel of actions

Redux-elements is built for eager execution of actions in the frontend and subsequent sync with a stream-processing backend, e.g. Apache Kafka.

This means that Redux-Elements needs to support roll-back and reordering of actions. An example is the following chain of events:

  • A frontend using Redux-elements dispatches and eagerly executes action a1, changing a part of the store. The frontend sends a1 via API to the backend.
  • Another frontend or part of the backend dispatches action a0, which arrives at the backend before action a1.
  • Action a0 is processed by the backend - the state in the backend is therefore defined by the actions sequence [a0]. Action a0 is sent to all frontends.
  • Action a1 arrives in the backend and is processed there - the "true" state is defined by the action sequence [a0, a1]. Action a1 (and its order in the action sequence) is sent back to all frontends.
  • Action a0 arrives in the frontend using Redux-elements. It needs to be inserted before all actions which are currently "local only" - i.e. don't have a response from backend yet. You can use the Redux-elements TimeMachine object for this, wrapping the action with TimeMachine.makeActionInsertBefore(a0, "id of a1"). Redux-elements efficiently recalculates the state from a0, leaving all previous (still valid) actions untouched.
  • Action a1 arrives back in the frontend using Redux-elements. Since it's already processed at the right position in the action sequence, nothing needs to be done except noting its "true" position in the backend sequence of actions.
import { createStore } from "redux";
import { TimeMachine } from "redux-elements";

// ...

const tm = new TimeMachine({
  users: userReducer,
  projects: projectReducer
})

const store = createStore(tm.reducer)

// ...

const action = tm.createRollbackAction("actionId5");
store.dispatch(action) // rolls back action with id "actionId5"

// ...

const actionNormal = {
  type: "ADD_USER",
  payload: { ... },
  actionId: "something"
}
const actionTimeTraveller = tm.makeActionInsertBefore(actionNormal, "actionId6");
store.dispatch(actionTimeTraveller) // action is executed before action with id "actionId6"

License

Redux-elements is published under MIT license.