deduce

2.0.0-2 • Public • Published

deduce

NPM version Downloads Build Status Coverage Status Tip

Ridiculously easy JavaScript state containers with reducer methods. Like Redux without all of the boilerplate.

Install

npm install --save deduce

Usage

// reducers.js
 
export function increment(state, val = 1) {
    return state + val;
}
 
export function decrement(state, val = 1) {
    return increment(state, -val);
}
 
// store.js
 
import deduce from 'deduce';
import * as reducers from './reducers';
 
const store = deduce(1, reducers);
 
store.addListener(() => {
    console.log(store.state);
});
 
store.increment();  // -> 2
store.increment(2); // -> 4
store.decrement();  // -> 3
store.decrement(2); // -> 1

API

deduce(initialState, reducers) : Store

  • initialState {*}
  • reducers {Object<String,Function>}

Store

.state

Current state of the store.

const store = deduce({ foo: 1 });
 
console.log(store.state); // -> { foo: 1 }

.addReducers(reducers): Store

  • reducers {Object<String,Function>}

Registers reducers to modify the state. Chainable.

store.addReducers({
    increment(state, val) {
        return {
            ...state,
            foo: state.foo + val,
        };
    },
});

.addReducersFor(property, reducers): Store

  • property {String}
  • reducers {Object<String,Function>}

Registers reducers to modify a specific state property. Chainable.

store.addReducersFor('foo', {
    increment(state, val) {
        return state + val;
    },
});

.addListener(callback): Function

  • callback {Function}

Adds a listener to be called any time the state is updated. Returns a function to remove the listener.

const removeListener = store.addListener(() => {
    console.log(store.state);
});
 
store.increment();

Why?

The typical Redux patterns entail a lot of boilerplate. The documented and accepted patterns for reducing boilerplate really just swap one kind for another:

Redux Example

Consider the following Redux example that creates a store with two numbers: foo which may be incremented and bar which may be decremented.

// foo
 
const FOO_INCREMENT = 'FOO_INCREMENT';
 
const fooInitial = 0;
 
const fooReducers = {
    [FOO_INCREMENT]: (state = fooInitial, action) {
        return state + action.payload;
    }
};
 
function foo(state = {}, action) {
    if (action.type in fooReducers) {
        return fooReducers[action.type](state, action);
    }
 
    return state;
}
 
function createFooIncrementAction(payload) {
    return {
        type: FOO_INCREMENT,
        payload
    };
}
 
// bar
 
const BAR_DECREMENT = 'BAR_DECREMENT';
 
const barInitial = 0;
 
const barReducers = {
    [BAR_DECREMENT]: (state = barInitial, action) {
        return state - action.payload;
    }
};
 
function bar(state, action) {
    if (action.type in barReducers) {
        return barReducers[action.type](state, action);
    }
 
    return state;
}
 
function createBarDecrementAction(payload) {
    return {
        type: BAR_DECREMENT,
        payload
    };
}
 
// store
 
import { createStore, combineReducers } from 'redux';
 
const reducer = combineReducers({ foo, bar });
const store = createStore(reducer, {});
 
// application
 
store.dispatch(createFooIncrementAction(1));
store.dispatch(createBarDecrementAction(1));
 
console.log(store.getState());
// {
//   foo: 1,
//   bar: -1
// }

Split that up into modules and you can see how new-comers could easily be overwhelmed when the underlying principles are beautifully clean and simple.

Deduce Example

Compare the above with this deduce example that does the same thing:

// foo
 
const fooInitial = 0;
 
const fooReducers = {
    incrementFoo(state = fooInitial, val) {
        return state + val;
    }
};
 
// bar
 
const barInitial = 0;
 
const barReducers = {
    decrementBar(state = barInitial, val) {
        return state - val;
    }
};
 
// store
 
import deduce from 'deduce';
 
const store = deduce()
    .addReducersFor('foo', fooReducers)
    .addReducersFor('bar', barReducers);
 
// application
 
store.incrementFoo(1);
store.decrementBar(1);
 
console.log(store.state);
// {
//   foo: 1,
//   bar: -1
// }

Contribute

Standards for this project, including tests, code coverage, and semantics are enforced with a build tool. Pull requests must include passing tests with 100% code coverage and no linting errors.

Test

$ npm test

MIT © Shannon Moeller

Package Sidebar

Install

npm i deduce

Weekly Downloads

24

Version

2.0.0-2

License

MIT

Unpacked Size

20.1 kB

Total Files

7

Last publish

Collaborators

  • shannonmoeller