Comparing version 0.0.1 to 0.0.2
@@ -1,5 +0,7 @@ | ||
export declare type Dispatcher = (reducer: Reducer<any>) => any; | ||
export declare type SyncReducer<State> = (state: State) => State; | ||
export declare type AsyncReducer<State> = (state: State) => (dispatch: Dispatcher) => any; | ||
export declare type Reducer<State> = SyncReducer<State> | AsyncReducer<State>; | ||
export declare type Reducer<State> = (state: State) => State; | ||
export declare type Listener = () => void; | ||
export declare type Unsubscribe = () => void; | ||
export declare type Middleware<State> = (store: Store<State>, reducer: Reducer<State>) => Reducer<State>; | ||
import thunkMiddleware from './middlewares/thunk'; | ||
export declare const thunk: typeof thunkMiddleware; | ||
export default class Store<State> { | ||
@@ -11,4 +13,6 @@ private state; | ||
getState: () => State; | ||
dispatch: Dispatcher; | ||
subscribe: (Function) => Function; | ||
dispatch: (reducer: any) => any; | ||
subscribe: (listener: Listener) => Unsubscribe; | ||
addMiddleware: (...middlewares: Middleware<State>[]) => this; | ||
applyMiddlewares: (reducer: Reducer<State>) => Reducer<State>; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
//export type Middleware<State> = (store: Store<State>, reducer: Reducer<State>) => void; | ||
var thunk_1 = require("./middlewares/thunk"); | ||
exports.thunk = thunk_1.default; | ||
var Store = (function () { | ||
@@ -12,9 +13,8 @@ function Store(initialState) { | ||
assertReducer(reducer); | ||
//const result = this.applyMiddlewares(reducer)(this.state); | ||
var result = reducer(_this.state); | ||
if (typeof result === 'function') | ||
return result(_this.dispatch, _this.getState); | ||
_this.state = result; | ||
_this.listeners.forEach(function (listener) { return listener(); }); | ||
return reducer; | ||
var finalReducer = _this.applyMiddlewares(reducer); | ||
if (typeof finalReducer === 'function') { | ||
_this.state = finalReducer(_this.state); | ||
_this.listeners.forEach(function (listener) { return listener(); }); | ||
} | ||
return finalReducer; | ||
}; | ||
@@ -24,4 +24,18 @@ this.subscribe = function (listener) { | ||
_this.listeners = _this.listeners.concat([listener]); | ||
return function () { return (_this.listeners = _this.listeners.filter(function (lis) { return lis !== listener; })); }; | ||
return function () { | ||
return (_this.listeners = _this.listeners.filter(function (lis) { return lis !== listener; })); | ||
}; | ||
}; | ||
this.addMiddleware = function () { | ||
var middlewares = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
middlewares[_i] = arguments[_i]; | ||
} | ||
assertMiddlewares(middlewares); | ||
_this.middlewares = _this.middlewares.concat(middlewares); | ||
return _this; | ||
}; | ||
this.applyMiddlewares = function (reducer) { | ||
return _this.middlewares.reduce(function (prevReducer, middleware) { return middleware(_this, prevReducer); }, reducer); | ||
}; | ||
this.state = initialState; | ||
@@ -40,8 +54,7 @@ } | ||
} | ||
/*function assertMiddlewares(middlewares: Function[]) { | ||
middlewares.forEach((middleware) => { | ||
if (typeof middleware !== 'function') | ||
throw new Error('Middleware is not a function: addMiddleware takes only middlewares as functions.'); | ||
}); | ||
}*/ | ||
function assertMiddlewares(middlewares) { | ||
if (middlewares.some(function (middleware) { return typeof middleware !== 'function'; })) { | ||
throw new Error('Middleware is not a function: addMiddleware takes only middlewares as functions.'); | ||
} | ||
} | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "repatch", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"description": "Dispatch reducers", | ||
@@ -26,2 +26,2 @@ "main": "lib/store/index", | ||
} | ||
} | ||
} |
# Repatch | ||
## Dispatch the reducers | ||
## Dispatch reducers | ||
The most of projects do not need sctrict action administration. Action types, action creators and reducers' action handlers are mutually assigned to each other. | ||
The most of redux projects do not need sctrict action administration. Action types, action creators and reducers' action handlers are mutually assigned to each other. | ||
The simplest way to keep immutable action controlled dataflow is dispatching pure functions (as reducers) to the store. | ||
So we have only actions which return reducers. | ||
```javascript | ||
@@ -28,3 +30,3 @@ const resolveFetchingUsers = users => state => ({ | ||
const store = new Store(initialState) | ||
const store = new Store(initialState); | ||
``` | ||
@@ -42,11 +44,44 @@ | ||
In async actions reducer returns a function. | ||
In async actions reducer returns a function (*delegate*). | ||
```javascript | ||
const updateUser = (delta) => (state) => async (dispatch, getState) => { | ||
const updateUser = delta => state => async (dispatch, getState) => { | ||
const editedUserId = getState().editedUser; | ||
dispatch(toggleSpinner(true)); | ||
await api.updateUser(editedUserId, delta); | ||
await dispatch(fetchUsers()); | ||
dispatch(toggleSpinner(false)); | ||
}; | ||
``` | ||
## Subreducers | ||
We do not need to reduce always the whole state of the store. A good practice to avoid this effort is using subreducers. | ||
Let's suppose we have the following state: | ||
```javascript | ||
const store = new Store({ | ||
userManagement: { | ||
users: [...], | ||
isFetching: false, | ||
error: null | ||
} | ||
}); | ||
``` | ||
Then we can make a subredcer for the `userManagement` section: | ||
```javascript | ||
const reduceUserManagement = reducer => state => ({ | ||
...state, | ||
userManagement: reducer(state.userManagement) | ||
}); | ||
``` | ||
After that reducing only the `userManagement` state it's easy: | ||
```javascript | ||
const rejectFetchingUsers = error => | ||
reduceUserManagement(state => ({ ...state, error, isFetching: false })); | ||
``` |
Sorry, the diff of this file is not supported yet
18219
24
219
85