updux/docs/concepts.md

112 lines
2.8 KiB
Markdown

# Updux concepts
## Actions and action generators
Updux assumes actions following the format
```js
{
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:
```js
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
```js
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.
```js
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
```