Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

chopped-redux

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

chopped-redux - npm Package Compare versions

Comparing version 3.0.0 to 4.0.0

22

index.js
module.exports = function (reducer, state, listeners) {
listeners = listeners || []
module.exports = function factory (update, state) {
var listeners = []
if (typeof reducer !== 'function') {
throw new TypeError('The `reducer` param must be a function.')
if (typeof update !== 'function') {
throw new TypeError('The `update` param must be a function.')
}

@@ -19,4 +19,6 @@

action = action || {}
state = reducer(state, action)
listeners.forEach(function (fn) { fn(action) })
state = update(state, action)
listeners.slice().forEach(function (fn) { fn(action) })
return action
}

@@ -37,4 +39,10 @@

dispatch: dispatch,
subscribe: subscribe
subscribe: subscribe,
get updater () {
return update
},
set updater (fn) {
update = fn
}
}
}
{
"name": "chopped-redux",
"version": "3.0.0",
"description": "A subset of @gaearon Redux",
"version": "4.0.0",
"description": "An implementation of @gaearon Redux",
"keywords": [

@@ -19,5 +19,3 @@ "flux",

"license": "MIT",
"dependencies": {
"curry": "^1.2.0"
},
"dependencies": {},
"devDependencies": {

@@ -24,0 +22,0 @@ "immutable": "^3.7.4",

# Chopped Redux
![npm version](https://img.shields.io/npm/v/chopped-redux.svg) ![npm downloads](https://img.shields.io/npm/dm/chopped-redux.svg)
![npm version](https://img.shields.io/npm/v/chopped-redux.svg)
This library is a subset of [@gaearon](https://github.com/gaearon) [Redux](https://github.com/gaearon/redux), which claims to be a "Predictable state container for JavaScript apps".
This library is an implementation (a subset?) of [@gaearon](https://github.com/gaearon) [Redux](https://github.com/gaearon/redux), which claims to be a "Predictable state container for JavaScript apps".
Redux is based on [Facebook's Flux](https://facebook.github.io/flux/) but it's a lot more simple a straightforward. Chopped Redux follows the same principles and ideas but cutting off features. If you care, it's 30 sloc (0.75 kB).
Redux is based on [Facebook's Flux](https://facebook.github.io/flux/) but it's a lot more simple a straightforward. Chopped Redux follows the same principles and ideas but cutting off features, namely all utility methods and ES2015/7 magic. Chopped is practically the same as Redux's 1.0 core, just [read the source](https://github.com/acstll/chopped-redux/blob/master/index.js).

@@ -13,4 +13,14 @@ This project follows [SemVer](http://semver.org/).

In the beginning, Redux was a [React](http://facebook.github.io/react/) thing. So I wanted to have a similar library not tight to any rendering/view-layer library, and I was mainly inspired by [this](https://github.com/gaearon/redux/pull/166) and [this](https://github.com/gaearon/redux/issues/113#issuecomment-114049804), ideas which made the Flux unidirectional data-flow very simple. Redux is [free from React](https://github.com/gaearon/redux/issues/230) starting at 1.0. Still Chopped is a simpler alternative to it (though Redux is itself very small and simple). The things you'll miss from Redux here are basically `Middleware`, ES2015/7 magic and restrictions. Hot-reloading and time-travel are possible if you know what you're doing, or **why** you're doing it, but it's **not built-in**.
In the beginning, Redux was a [React](http://facebook.github.io/react/) thing. So I wanted to have a similar library not tight to any rendering/view-layer library, and I was mainly inspired by [this](https://github.com/gaearon/redux/pull/166) and [this](https://github.com/gaearon/redux/issues/113#issuecomment-114049804), ideas which made the Flux unidirectional data-flow very simple. Redux is [free from React](https://github.com/gaearon/redux/issues/230) and free from `class`es starting at 1.0, so there's no reason for you to use Chopped instead of the genuine Redux if you don't find any of the key differences useful to you.
### Key differences from Redux
- There’s no init dispatch on `createStore()`, you need to do that yourself when you know it’s time to initialize your state.
- You can pass anything to `dispatch()`, not only a plain object, it's your responsibility to handle that in the `update function.
- You can call `dispatch()` with no arguments (an empty object will get dispatched), useful for initializing.
- The dispatched `action` gets passed to listeners.
- The `reducer` function is called `update` (this is just aesthetics).
- There's an extra method `replaceState` (use carefully, the whole point of Redux is to make state changes sane and predictable).
- `getReducer` and `replaceReducer` methods are missing.
## Install

@@ -33,6 +43,6 @@

```js
var chopped = require('chopped-redux')
var createStore = require('chopped-redux')
function reducer (state, action) {
state = state || 0 // initialize state if empty
function update (state, action) {
state = state || 0 // always initialize state if empty

@@ -46,3 +56,3 @@ if (action.type === 'increment') {

var store = chopped(reducer)
var store = createStore(update)
var action = { type: 'increment' } // actions are objects

@@ -61,5 +71,6 @@

- All state of your app goes into `state`, a single object
- The `reducer` function is **pure** (it should *only* update and return new `state` and nothing else)
- `actions` are plain objects with at least two properties `type` (String) and `payload` (Mixed)
- You do async inside helper functions [(action dispatchers)](#async-and-action-creators) that call `dispatch` when done
- The `update` function is **pure** (it should *only* update and return new `state` and nothing else)
- The `update` function always return some initial state if undefined.
- `actions` are plain objects with at least one property: `type` (String), and an optional `payload` (Mixed).
- You do async inside functions [(action dispatchers)](#async-and-action-creators) that call `dispatch` when done

@@ -79,11 +90,10 @@ ## API

The factory has a single mandatory param which is a `reducer` function.
The factory has a single mandatory param which is a `update` function.
#### `createStore(reducer[, initialState, listeners])`
#### `createStore(update[, initialState])`
- *reducer* `Function`
- *update* `Function`
- *initialState* `Mixed` Anything you want to hold your state in
- *listeners* `Array` Listener callbacks that subscribe to dispatches
The `reducer` function should have the following signature:
The `update` function should have the following signature:

@@ -101,3 +111,3 @@ ```js

```js
state = reducer(state, action)
state = update(state, action)
```

@@ -128,23 +138,7 @@

### Helpers
#### `wrap(methods, dispatch)`
Available at `require('chopped-redux/wrap')`.
This is a highly opinionated helper that binds your action dispatchers (aka action creators) to a `store.dispatch` instance, by currying them.
This functions are meant to have this signature `function (dispatch, payload) {}`. See [Async and action creators](#async-and-action-creators) below.
- Returns `Object` The same methods wrapping the dispatcher
- *methods* `Object` An object with your action dispatcher functions
- *dispatch* `Function` The `dispatch` method from your `store` instance
---
## Async and action creators
Handling async stuff in vanilla Flux is a pain. In the beginning of Flux we were making API calls inside our Stores, that turned out to be a bad idea. So they came up with this pompous concept of Action Creators to confuse us all (at least for a while). [If you’re still confused, Action Creators are functions that return Actions, which are simply objects; so Action == plain object, Action Creator == function that creates an Action.] Apparently no-one knows how to do this right.
Handling async stuff in vanilla Flux is a pain. In the beginning of Flux we were making API calls inside our Stores, that turned out to be a bad idea. So they came up with this pompous concept of Action Creators to confuse us all (at least for a while). [If you’re still confused, Action Creators are functions that return Actions, which are simply objects; so Action == plain object; Action Creator == function that creates an Action object.] Apparently no-one knows how to do this right.
In Redux there’s middleware. The [thunk](https://github.com/gaearon/redux-thunk) middleware *transforms* an Action Creator (they call it “intent”) into an object that you can dispatch, and you *create* Action Creators like this:
In Redux there’s middleware. The [thunk](https://github.com/gaearon/redux-thunk) middleware allows you to literally dispatch a function, and your Action Creators look like this:

@@ -169,3 +163,3 @@ ```js

I prefer to (partly) avoid the concept of Action Creators with a simpler approach, namely this:
I prefer a simpler and more explicit approach based only on the necessity of delaying the dispatch, namely this:

@@ -185,5 +179,5 @@ ```js

in which the `dispatch` callback always gets passed in as first argument.
a function in which the `dispatch` callback always gets passed-in as first argument. You could also pass in the very `store` instance if you need to `getState()`.
If you care about names, I would call this an *action dispatcher* function, because that’s what it does. There’s no nesting, no type checking, no complexity. You just pass in a callback for dispatching an action with some payload. You’re just delegating `dispatch`ing actions to a helper function to do some things before the dispatch.
I would call this an *action dispatcher* function, because that’s what it does. There’s no nesting, no type checking, no complexity. You just pass in a callback for dispatching an action with some payload. You’re just delegating `dispatch`ing actions to a helper function to do some things before the dispatch.

@@ -202,3 +196,3 @@ If you don’t need async, simply `dispatch` the action directly and you’ve got one less function to care about.

https://gist.github.com/vslinko/cab24085f029def8997b by @vslinko
A [gist](https://gist.github.com/vslinko/cab24085f029def8997b) by [@vslinko](http://github.com/vslinko)
[The Evolution of Flux Frameworks](https://medium.com/@dan_abramov/the-evolution-of-flux-frameworks-6c16ad26bb31)

@@ -205,0 +199,0 @@

@@ -6,3 +6,2 @@

var createStore = require('../')
var wrap = require('../wrap')

@@ -13,3 +12,3 @@ // Action types

// Action factories (creators)
// Action helpers
var increment = function (dispatch) {

@@ -26,4 +25,4 @@ dispatch({ type: INCREMENT_COUNTER })

// Reducers
var reducer = function (state, action) {
// Updaters
var update = function (state, action) {
state = state || { counter: 10 }

@@ -42,3 +41,3 @@

}
var immutableReducer = function (state, action) {
var immutableUpdate = function (state, action) {
switch (action.type) {

@@ -56,3 +55,3 @@ case INCREMENT_COUNTER:

test('factory', function (t) {
test('Factory', function (t) {
t.plan(2)

@@ -66,3 +65,3 @@

createStore()
}, 'throws if missing reducer param')
}, 'throws if missing update param')

@@ -72,26 +71,30 @@ t.notEqual(a, b, 'no singleton')

test('mutable, listeners', function (t) {
t.plan(4)
test('Dispatching', function (t) {
t.plan(2)
var store = createStore(reducer, state)
var store = createStore(update)
t.doesNotThrow(store.dispatch, 'empty is possible')
store.subscribe(function () {})
var unsubscribe = store.subscribe(function () { t.pass('listener called') })
store.subscribe(function () {})
var result = store.dispatch({ foo: 'bar' })
t.equal(result.foo, 'bar', 'returns given action')
})
test('Mutable', function (t) {
t.plan(3)
var store = createStore(update, state)
increment(store.dispatch)
t.equal(store.getState().counter, 2, 'action dispatched 1')
unsubscribe()
decrement(store.dispatch)
t.equal(store.getState().counter, 1, 'action dispatched 1')
t.equal(store.getState().counter, 1, 'action dispatched 2')
t.equal(store.getState(), state, 'state is the same mutable object')
t.equal(store.getState(), state, 'state is the same (mutable) object')
})
test('immutable', function (t) {
test('Immutable', function (t) {
t.plan(3)
var store = createStore(immutableReducer, immutableState)
var store = createStore(immutableUpdate, immutableState)

@@ -102,3 +105,3 @@ increment(store.dispatch)

decrement(store.dispatch)
t.equal(store.getState().get('counter'), 1, 'action dispatched 1')
t.equal(store.getState().get('counter'), 1, 'action dispatched 2')

@@ -108,16 +111,37 @@ t.notEqual(store.getState(), immutableState, 'state is not the same object')

test('no initial state provided', function (t) {
test('Listeners', function (t) {
t.plan(5)
var store = createStore(immutableUpdate, Immutable.Map({ counter: 5 }))
var off1 = store.subscribe(function () { t.pass('get called 1 (x2)') })
var off2 = store.subscribe(function () {
t.equal(store.getState().get('counter'), 6, 'can be remove from within (x1)')
off2()
})
var off3 = store.subscribe(function () { t.pass('get called 2 (x2)') })
store.dispatch({ type: INCREMENT_COUNTER })
store.dispatch()
off1()
off3()
store.dispatch()
})
test('No initial state provided', function (t) {
t.plan(1)
var store = createStore(reducer, null)
var store = createStore(update, null)
store.dispatch({ type: DECREMENT_COUNTER })
t.equal(store.getState().counter, 9, 'gets set in reducer')
t.equal(store.getState().counter, 9, 'gets set by updater')
})
test('first-class dispatch and getState, no bind', function (t) {
test('First-class dispatch and getState, no bind', function (t) {
t.plan(2)
var initialState = { counter: 5 }
var store = createStore(reducer, initialState)
var store = createStore(update, initialState)

@@ -133,6 +157,6 @@ function wrapper (fn) {

t.equal(getState(), initialState, 'getState')
t.equal(getState(), initialState, 'for getState')
increment(dispatch)
t.equal(getState().counter, 6, 'dispatch')
t.equal(getState().counter, 6, 'for dispatch')
})

@@ -144,3 +168,3 @@

var initialState = { counter: -1 }
var store = createStore(reducer, initialState)
var store = createStore(update, initialState)

@@ -155,29 +179,17 @@ increment(store.dispatch)

test('wrap/curry action factories', function (t) {
test('`updater` property', function (t) {
t.plan(3)
var inc = function (dispatch, data) {
t.equal(data.foo, 'bar', 'arguments get passed in')
var store = createStore(update)
dispatch({
type: INCREMENT_COUNTER
})
}
store.dispatch()
t.equal(store.getState().counter, 10)
var store = createStore(reducer, { counter: 20 })
var actions = wrap({ increment: inc }, store.dispatch)
t.equal(typeof store.updater, 'function', 'is getter')
actions.increment({ foo: 'bar' })
t.equal(store.getState().counter, 21, 'works')
t.throws(function () {
wrap({ increment: increment }, store.dispatch)
}, 'must take at least 2 arguments')
store.updater = function (state, action) {
return { counter: 99 }
}
store.dispatch()
t.equal(store.getState().counter, 99, 'is setter')
})
test('empty dispatching', function (t) {
t.plan(1)
var store = createStore(reducer)
t.doesNotThrow(store.dispatch, 'is possible')
})
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc