updux/docs/concepts.md

2.8 KiB

Updux concepts

Actions and action generators

Updux assumes actions following the format

{
    type: 'theTypeName',
    payload: {
        ...
    }
}

The important part is having action parameters in the payload property. The actions can also have other properties, like meta. They are mostly ignored by Updux.

Updux provides an action generator, but you can roll your own if you do wish. All it needs to do to be recognized as an action generator by Updux is

  1. To be a function returning an action (a plain object with at least a type property).
  2. The function also needs to have a type property itself.

For example, the following function would work:

function action(type) {
    return Object.assign( payload => ({type, payload}), { type } )
}

Mutations

The transformations typically done by a Redux's reducer are called 'mutations' in Updux. A mutation is a function with the following signature:

( payload, action ) => state => {
    // ... stuff done here
    return new_state;
}

The inversion and chaining of parameters from the usual Redux reducer's signature is there to work with updeep's curried nature. The expansion of the usual action into (payload, action) is present because in most cases payload is what we're interested in. So why not make it easily available?

Leftover mutation

A mutation associated to the special action + will match any action that haven't been explicitly dealt with with any other defined mutation.

todosUpdux.addMutation( '+', (payload,action) => state => {
    console.log("hey, action has no mutation! ", action.type);
});

Effects

Updux effects are redux middlewares. I kept that format, and the use of next mostly because I wanted to give myself a way to alter actions before they hit the reducer, something that redux-saga and rematch don't allow.

An effect has the signature

const effect = ({ getState, dispatch }) => next => action => { ... }

Selectors

Selectors are used to get data derived from the store's state.

The signature of a selector function is either (state) => result or (state) => (...args) => result. The selector instances attached to a store's getState already do the first call on state, so you don't have to.


const dux = new Updux({
    initial: {
        foo: 1, 
    },
    selectors: {
        getFoo: ({foo}) => foo,
        getFooPlus: ({foo}) => increment => foo + increment,
    }
});

console.log(dux.selectors.getFoo({foo: 2})); // prints 2 
console.log(dux.selectors.getFooPlus({foo: 2})(3)); // prints 5

const store = dux.createStore();

console.log(store.selectors.getFoo({foo: 2}));        // prints 2 
console.log(store.selectors.getFooPlus({foo: 2})(3)); // prints 5

console.log(store.getState.getFoo());      // prints 2 
console.log(store.getState.getFooPlus(3)); // prints 5