Go to file
2019-11-05 13:06:17 -05:00
dist churning things around 2019-11-04 20:34:14 -05:00
docs churning things around 2019-11-04 20:34:14 -05:00
src add sink mutations 2019-11-05 13:06:17 -05:00
.gitignore housecleaning 2019-10-22 10:26:04 -04:00
.travis.yml travis config 2019-10-24 11:44:51 -04:00
babel.config.js remove the pipeline operator 2019-10-21 11:40:08 -04:00
Changes churning things around 2019-11-04 20:34:14 -05:00
index.d.ts move buildInitial to ts 2019-10-23 12:47:11 -04:00
index.test-d.ts move buildInitial to ts 2019-10-23 12:47:11 -04:00
jest.config.js make jest work with js and ts 2019-10-23 12:56:12 -04:00
package.json churning things around 2019-11-04 20:34:14 -05:00
README.md point to the github page 2019-11-04 20:53:32 -05:00
TODO churning things around 2019-11-04 20:34:14 -05:00
tsconfig.json churning things around 2019-11-04 20:34:14 -05:00
typedoc.json churning things around 2019-11-04 20:34:14 -05:00

What's Updux?

So, I'm a fan of Redux. Two days ago I discovered rematch alonside a few other frameworks built atop Redux.

It has a couple of pretty good ideas that removes some of the boilerplate. Keeping mutations and asynchronous effects close to the reducer definition? Nice. Automatically infering the actions from the said mutations and effects? Genius!

But it also enforces a flat hierarchy of reducers -- where is the fun in that? And I'm also having a strong love for Updeep, so I want reducer state updates to leverage the heck out of it.

All that to say, say hello to Updux. Heavily inspired by rematch, but twisted to work with updeep and to fit my peculiar needs. It offers features such as

  • Mimic the way VueX has mutations (reducer reactions to specific actions) and effects (middleware reacting to actions that can be asynchronous and/or have side-effects), so everything pertaining to a store are all defined in the space place.
  • Automatically gather all actions used by the updux's effects and mutations, and makes then accessible as attributes to the dispatch object of the store.
  • Mutations have a signature that is friendly to Updux and Immer.
  • Also, the mutation signature auto-unwrap the payload of the actions for you.
  • TypeScript types.

Fair warning: this package is still very new, probably very buggy, definitively very badly documented, and very subject to changes. Caveat Maxima Emptor.

Synopsis

import updux from 'updux';

import otherUpdux from './otherUpdux';

const {
    initial,
    reducer,
    actions,
    middleware,
    createStore,
} = new Updux({ 
    initial: {
        counter: 0,
    },
    subduxes: {
        otherUpdux,
    },
    mutations: {
        inc: ( increment = 1 ) => u({counter: s => s + increment })
    },
    effects: {
        '*' => api => next => action => {
            console.log( "hey, look, an action zoomed by!", action );
            next(action);
        };
    },
    actions: {
        customAction: ( someArg ) => ({ 
            type: "custom", 
            payload: { someProp: someArg } 
        }),
    },

});

const store = createStore();

store.dispatch.inc(3);

Description

The formal documentation of the class Updux and its associated functions and types can be found over here.

Exporting upduxes

If you are creating upduxes that will be used as subduxes by other upduxes, or as ducks-like containers, I recommend that you export the Updux instance as the default export:

import Updux from 'updux';

const updux = new Updux({ ... });

export default updux;

Then you can use them as subduxes like this:

import Updux from 'updux';
import foo from './foo'; // foo is an Updux
import bar from './bar'; // bar is an Updux as well

const updux = new Updux({
    subduxes: {
        foo, bar
    }
});

Or if you want to use it:

import updux from './myUpdux';

const {
    reducer,
    actions: { doTheThing },
    createStore,
    middleware,
} = updux;

Usage with Immer

While Updux was created with Updeep in mind, it also plays very well with Immer.

For example, taking this basic updux:

import Updux from 'updux';

const updux = new Updux({
    initial: { counter: 0 },
    mutations: {
        add: (inc=1) => state => { counter: counter + inc } 
    }
});
    

Converting it to Immer would look like:

import Updux from 'updux';
import { produce } from 'Immer';

const updux = new Updux({
    initial: { counter: 0 },
    mutations: {
        add: (inc=1) => produce( draft => draft.counter += inc ) } 
    }
});
    

But since typing produce over and over is no fun, groomMutations can be used to wrap all mutations with it:

import Updux from 'updux';
import { produce } from 'Immer';

const updux = new Updux({
    initial: { counter: 0 },
    groomMutations: mutation => (...args) => produce( mutation(...args) ),
    mutations: {
        add: (inc=1) => draft => draft.counter += inc 
    }
});