# redux-elements

> Opinionated framework for redux state elements

Latest version **1.12.3** (published 2018-07-17) · MIT license · 0 weekly downloads

## Install

```sh
npm install redux-elements
pnpm add redux-elements
yarn add redux-elements
bun add redux-elements
```

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: has types; no vulnerabilities; high quality score.

Warnings: low downloads; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.12.3 |
| Published | 2018-07-17 |
| First published | 2018-02-10 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 8 |
| Unpacked size | 888.9 KB |
| Known vulnerabilities | 0 (+1 in 1 direct dependencies) |
| Install scripts | no |
| Author | Philipp Bodewig |
| Maintainers | philipp.bodewig |
| Keywords | redux, crud, reselect, database |

## Links

- npm: https://www.npmjs.com/package/redux-elements
- Repository: https://github.com/fintu/redux-elements
- Homepage: https://github.com/fintu/redux-elements#readme
- Issues: https://github.com/fintu/redux-elements/issues
- npm.io page: https://npm.io/package/redux-elements

## Dependencies (8)

- [uuid](https://npm.io/package/uuid.md) ^3.2.1
- [jsdoc](https://npm.io/package/jsdoc.md) ^3.5.5
- [lodash](https://npm.io/package/lodash.md) ^4.17.5
- [reselect](https://npm.io/package/reselect.md) ^3.0.1
- [immutable](https://npm.io/package/immutable.md) ^4.0.0-rc.9
- [redux-saga](https://npm.io/package/redux-saga.md) ^0.16.0
- [@types/uuid](https://npm.io/package/@types/uuid.md) ^3.4.3
- [@types/lodash](https://npm.io/package/@types/lodash.md) ^4.14.112

## Recent versions

- 1.12.3 (latest) — 2018-07-17
- 1.12.2 — 2018-07-15
- 1.12.1 — 2018-07-15
- 1.12.0 — 2018-07-15
- 1.11.9 — 2018-07-11
- 1.11.8 — 2018-07-11
- 1.11.7 — 2018-06-15
- 1.11.6 — 2018-06-12
- 1.11.4 — 2018-06-12
- 1.11.3 — 2018-04-15
- 1.11.2 — 2018-04-12
- 1.11.1 — 2018-02-26
- 1.11.0 — 2018-02-25
- 1.9.0 — 2018-02-25
- 1.8.0 — 2018-02-21
- … 8 more at https://npm.io/package/redux-elements/versions

## 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](https://fintu.github.io/redux-elements/index.html).

## Installation

You can install this repository via [npm](https://www.npmjs.com/package/redux-elements).

```
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:

```javascript
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:

```javascript
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](https://fintu.github.io/redux-elements/tutorial-selectors.html) 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.


```javascript
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.

---
_Source: https://npm.io/package/redux-elements · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
