https://github.com/medihack/redux-pouchdb-plus
Synchronize Redux store with PouchDB to have a persistent store.
https://github.com/medihack/redux-pouchdb-plus
Last synced: 3 months ago
JSON representation
Synchronize Redux store with PouchDB to have a persistent store.
- Host: GitHub
- URL: https://github.com/medihack/redux-pouchdb-plus
- Owner: medihack
- License: mit
- Created: 2016-01-27T20:33:02.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2020-04-08T08:28:35.000Z (about 5 years ago)
- Last Synced: 2025-03-08T12:07:54.176Z (3 months ago)
- Language: JavaScript
- Size: 103 KB
- Stars: 75
- Watchers: 3
- Forks: 24
- Open Issues: 6
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Redux PouchDB Plus
## About
**Redux PouchDB Plus** synchronizes a [Redux](rackt.github.io/redux) store with a [PouchDB](http://pouchdb.com/) database.
This code is heavily inspired (and some code reused) by Vicente de Alencar's [redux-pouchdb](https://github.com/vicentedealencar/redux-pouchdb).
So all Kudos to him. The rewrite was necessary to allow the following extras:- Have different Pouch databases for different reducers.
- Allow to switch databases dynamically.
- Support for other state types (like [Immutable](https://facebook.github.io/immutable-js/) states).
- Provide several callbacks (when initialization and database access happens).
- Allow custom name for PouchDB document used by reducer. (great for multi-user applications)The code is quite well tested using [tape](https://github.com/substack/tape).
## Usage
### General setup
The reducers you wish to persist should be enhanced with this higher order reducer (`persistentReducer`).
``` js
import { persistentReducer } from 'redux-pouchdb-plus';const counter = (state = {count: 0}, action) => {
switch(action.type) {
case INCREMENT:
return { count: state.count + 1 };
case DECREMENT:
return { count: state.count - 1 };
default:
return state;
}
};const finalReducer = persistentReducer(counter);
```Compose a store enhancer (`persistentStore`) with other enhancers in order to initialize the persistence.
``` js
import { persistentStore } from 'redux-pouchdb-plus';const db = new PouchDB('dbname');
//optional
const applyMiddlewares = applyMiddleware(
thunkMiddleware,
loggerMiddleware
);const createStoreWithMiddleware = compose(
applyMiddlewares,
persistentStore({db})
)(createStore);const store = createStoreWithMiddleware(finalReducer, initialState);
```You may also provide a specific database for this reducer (it is prioritized over
the provided database to the store).```js
const db2 = new PouchDB('another_dbname');
const finalReducer = persistentReducer(counter, {db: db2});
```A custom name (\_id) can also be given to the document created/used for the reducer.
```js
const finalReducer = persistentReducer(counter, {name: 'custom name'});
```### Switching databases during runtime
You may also provide a function that return a database connector instead of the
connector itself. This makes it possible to switch databases dynamically during runtime.```js
import { reinit } from 'redux-pouchdb-plus';let dbChoice = 1;
const db = (reducerName, store, additionalOptions) => {
if (dbChoice === 1)
return new PouchDB('dbname1');
else
return new PouchDB('dbname2');
}// uses 'dbname1' database
const finalReducer = persistentReducer(counter, {db});// switch to 'dbname2' database
dbChoice = 2;
// reinitialize reducer counter
store.dispatch(reinit('counter'));
// reinitialize all reducers
store.dispatch(reinit());
```### Check if database is in sync
With the `inSync` method you can check if all state changes of persistent
reducers are saved to the database or if there is some saving in progress.```js
import { inSync } from 'redux-pouchdb-plus';if (inSync()) {
// do something if the reducer states and the database are in sync
}
```### Use Immutable js states
You can use [Immutable.js](https://facebook.github.io/immutable-js/) states
in your reducers by providing some serialization helpers as options.```js
// import the necessary immutable stuff
import { Map, toJS, fromJS, is } from 'immutable'// setup your reducer with immuatable state
const counter = (state = Map({count: 0}), action) => {
switch(action.type) {
case INCREMENT:
return { count: state.count + 1 };
case DECREMENT:
return { count: state.count - 1 };
default:
return state;
}
};// provide the following options to make the serialization to the
// database work
const finalReducer = persistentReducer(counter, {
toPouch: toJS,
fromPouch: fromJS,
isEqual: is
});
```### Provided callback functions
You may provide the following callback functions as addition options to
`persistentReducer` or `persistentReducer`:```js
// example for persistentStore, but works the same for persistentReducer function.
persistentStore(counter, {
db,
name,
onInit: (reducerName, reducerState, store) => {
// Called when this reducer was initialized
// (the state was loaded from or saved to the
// database for the first time or after a reinit action).
},
onUpdate: (reducerName, reducerState, store) => {
// Called when the state of reducer was updated with
// data from the database.
// Cave! The store still contains the state before
// the updated reducer state was applied to it.
},
onSave: (reducerName, reducerState, store) => {
// Called every time the state of this reducer was
// saved to the database.
}
});
```Additionally you may provide an `onReady` callback on the store that is called
every time all persistent recuders finished the initialization.```js
persistentStore(counter, {
db,
onReady: (store) => {
// Called when all reducers are initialized (also after
// a reinit for all reducers is finished).
}
}
```## Notes
The current behavior is to have one document for each persisted reducer that looks like:
``` js
{
_id: 'reducerName', // the name the reducer function, or the name provided by {name: 'custom name'}
state: {}|[], // the state of the reducer
_rev: '' // pouchdb keeps track of the revisions
}
```