Gathering detailed insights and metrics for redux-replicate
Gathering detailed insights and metrics for redux-replicate
Gathering detailed insights and metrics for redux-replicate
Gathering detailed insights and metrics for redux-replicate
redux-replicate-localforage
Replicator for `redux-replicate` designed to locally persist the state of `redux` stores using `localforage`.
redux-replicate-fs
Replicator for `redux-replicate` designed to persist the state of `redux` stores using Node's `fs`.
redux-replicate-memory
Replicator for `redux-replicate` designed to *synchronously* persist the state of `redux` stores in memory. Useful for universal rendering of replicator query results and optimistic queries.
lumbur
Boilerplate w/ generator for building universal, extendable, and reusable React applications with `react-redux-provide`.
npm install redux-replicate
Typescript
Module System
Node Version
NPM Version
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
Creates a Redux store enhancer designed to replicate actions and states.
npm install redux-replicate --save
Many times you'll find yourself manually retrieving data and updating the state(s) of your store(s) based on the result. This library allows you to do this automatically and in a modular way.
Replication is a key concept when building any stateful application. When implemented correctly, it allows you to decouple data initialization, storage, and retrieval from your application so that your only concern is rendering its state. It allows you declaratively connect application state to data sources and create efficient, scalable, and reliable software with minimal effort.
You can:
Replicate specific state keys to some data source (database, API, etc.) whenever they change.
Replicate the entire state to some data source (database, API, etc.) whenever anything changes.
Automatically initialize state from some data source, synchronously or asynchronously.
Give the server full authority over the initial state and/or allow the client to override the initial state with their own values.
Instantly add real-time functionality to keep clients in sync with each other.
Instantly add or remove any number of data sources (databases, API, sockets, etc.).
If this is new to you, see Wikipedia's State machine replication page for more about it!
replicate
- Function which creates and returns the store enhancer based on the replication
passed to it. See the Usage section below.storeKeysEqual
- Accepts 2 store keys as arguments and returns true if they match.GET_INITIAL_STATE
- Dispatched immediately before calling a replicator's getInitialState
method.
GOT_INITIAL_STATE
- Dispatched after a replicator calls setState
within its getInitialState
method.
INITIAL_STATE_ERROR
- Dispatched when a replicator calls setError
within its getInitialState
method.
REPLICATE_INITIAL_STATE
- If using replication.clientState
or if a replicator passes undefined
to setState
within its getInitialState
method and the store's default initial state should be replicated (via either replication.create
or replication.clientState
), this will be dispatched prior to replicating the state (via the replicator's onStateChange
method).
REPLICATED_INITIAL_STATE
- Applicable only in conjunction with REPLICATE_INITIAL_STATE
. Dispatched when a replicator calls setState
or setStatus
within its onStateChange
method.
REPLICATE_STATE
- Dispatched immediately before calling a replicator's onStateChange
method.
REPLICATED_STATE
- Dispatched when a replicator calls setState
or setStatus
within its onStateChange
method.
STATE_CHANGE_ERROR
- Dispatched when a replicator calls setError
within its onStateChange
method.
SET_STATE
- Used internally when setting the state via store.setState
, but you can dispatch this action along with nextState
if for some reason you need to manually override the store's current state.
FULLY_INITIALIZED
- Dispatched after replication as fully initialized.
Call the replicate
function (default export) with the following options (as keys within an object) to create a store enhancer.
Typically a string, but this can be anything. It's passed to your replicators so they know where and/or how to replicate data. If you're using reducerKeys
, each reducerKey
is included in an object with this key
when calling a replicator's getInitialState
and onStateChange
methods.
Optional boolean value, array of strings, or object containing boolean values. This is helpful (and recommended!) if you're using Redux's combineReducers
function (or similar) and want to replicate changes to individual keys within the store's state object, rather than the entire state tree.
If an array, it will replicate only the keys within the array.
If an object, it will be compared to the clientState
(see below). All keys within the object will be replicated, but only the keys with truthy values will be initialized. This is useful if you want the server to be able to specify a custom initial state while also allowing the client to override the server's initial state.
If true
, it will replicate all keys.
If either false
or omitted, it will replicate the entire state object when calling getInitialState
and onStateChange
- i.e., it won't iterate over each reducerKey
even when combineReducers
is used.
Optional boolean value or object used for specifying whether or not the key
(or reducerKeys
if used) should be queryable by value. Defaults to false
.
If true
and not using reducerKeys
, then the key
will be queryable by value (current state).
If true
and using reducerKeys
, then each reducerKey
will be queryable by value (current state).
An object specifies which reducerKeys
are queryable by value (current state) where the keys within the object correspond to each reducerKey
and the values should be truthy.
If false
, values (current states) will not be queryable.
Set this to true
to ensure initial states are replicated.
Optional object used when determining which reducerKeys
should be initialized on the client. This object should be the initial state provided to the client by the server. If no clientState
, the client will be able to fully override the initial state with their own replicated values.
Either a single replicator or an array of replicators. See the Replicators section below.
Replicators can:
Initialize the state of the store, synchronously and/or asynchronously.
Save state changes to data sources.
Allow current states to be queryable.
Send actions to clients, other servers, etc.
Be packaged and easily reusable!
A replicator is a plain object of the following shape.
Optional function to set the store's initial state, synchronously or asynchronously. The following options are passed to it within an object:
Object store,
String reducerKey,
Function setState,
Function setError
If using reducerKeys
, this function is called once per initializable reducerKey
(passing each reducerKey
per call).
If not using reducerKeys
, this function is called only once.
Either the setState
or the setError
function must be called for the store to finish initializing, regardless of whether or not the state exists within the data source.
Example (from redux-replicate-localforage
):
1const getItemKey = (key, reducerKey) => reducerKey 2 ? `${key}/${reducerKey}` 3 : key; 4 5const getInitialState = ({ store, reducerKey, setState, setError }) => { 6 localforage 7 .getItem(getItemKey(store.key, reducerKey)) 8 .then(state => setState(parse(state))) 9 .catch(setError); 10};
Optional function called after initialization. The following options are passed to it within an object:
Object store
Example:
1import { storeKeysEqual } from 'redux-replicate'; 2 3const onReady = ({ store }) => socket.on('action', ({ key, action }) => { 4 if (storeKeysEqual(key, store.key)) { 5 store.dispatch(action); 6 } 7});
Optional function to replicate the state and/or the action upon state changes. The following options are passed to it within an object:
Object store,
String reducerKey,
Mixed state,
Mixed nextState,
Boolean queryable,
Object action,
Mixed clientState,
Mixed create,
Function setState,
Function setStatus,
Function setError
If using reducerKeys
, this function is called once per reducerKey
with state
, nextState
, and queryable
representing each particular reducerKey
.
If not using reducerKeys
, this function is called only once.
You should always call either create
(if it's a function), setState
, setStatus
, or setError
when the replication has completed.
Example (from redux-replicate-localforage
):
1const onStateChange = ({ 2 store, 3 reducerKey, 4 nextState, 5 queryable, 6 setStatus, 7 setError 8}) => { 9 localforage 10 .setItem(getItemKey(store.key, reducerKey), stringify(nextState)) 11 .then(() => setStatus()) 12 .catch(setError); 13 14 if (queryable) { 15 // in the case of simple key-value stores like localforage where the 16 // ability to query by value doesn't come with it, you can store a 17 // custom map of values to keys to be used for querying... 18 // in most cases you won't have to implement this functionality though :) 19 } 20};
Optional function to replicate the state and/or the action upon any reduction, regardless of whether or not the store's state has changed. This is called only after initialization. If you want to replicate actions, this is the place to do it. The following options are passed to it within an object:
Object store,
Mixed state,
Mixed nextState,
Object action
This function is only called once per reduction. A quick state !== nextState
check here would let you know if any change has taken place, regardless of whether or not you're using reducerKeys
.
Example:
1function postReduction({ store, state, nextState, action }) { 2 if (state !== nextState) { 3 socket.emit('action', { key: store.key, action }); 4 } 5}
Optional function to handle some query. The query
argument can be specific to your implementation, but it's best to follow convention. In the future, we may solidify a standard for this. The following options are passed to it within an object:
Object store,
Mixed query,
Mixed options,
Function setResult,
Function setError
If using reducerKeys
, the query
argument should typically be an object containing reducerKey
to state (value) pairs.
If not using reducerKeys
, the query
argument should typically be the entire state.
These are just general guidelines though, as it all really comes down to how your particular database or API is designed to handle queries.
Example:
1function handleQuery({ query, options, setResult, setError }) { 2 database 3 .find(query, options) 4 .then(setResult) 5 .catch(setError); 6}
The enhancer adds the following to the store
object.
The current key
.
(String key, Function readyCallback)
Sets the current key
. The readyCallback
is called after all of the replicators have fully initialized based on the new key
.
(Mixed nextState)
You typically shouldn't need to use this, as state changes should almost always occur as a result of store.dispatch(action)
. But it may be useful for keeping a store's state synchronized with some data source which doesn't rely on actions. If using reducerKeys
, the nextState
is expected to be an object and is merged into the current state, similar to React's setState
. If not using reducerKeys
, the nextState
replaces the current state entirely.
An array containing each replication
object (options) passed to the replicate
function (this package's default export). In most cases, this will contain only a single replication
object, but it's mostly used internally for cases where multiple replicate
enhancers are applied.
(Function readyCallback)
You can use this if you know your replicator(s) asynchronously initialize the store's state and would like to do something immediately after initialization. The readyCallback
will receive the store
within an object.
Used internally for holding each readyCallback
passed to store.onReady
.
If for some reason you need to know whether or not getInitialState
has completed, you can check this boolean property. It will be true
after initialization.
See redux-replicate-fs
, a replicator that persists the state of your store(s) and handles queries using Node's file system API.
react-redux-provide
Replication and providers work great together! Providers help you fully reap the benefits of replication. Below you can see how, with just a few lines of code, we enable real-time chat functionality and replicate the states of entries and comments to RethinkDB.
1// src/replication.js 2 3import rethink from 'redux-replicate-rethink'; 4import socket from 'redux-replicate-socket'; 5import * as providers from './providers/index'; 6 7// replication `key` defaults to each provider instance's key, 8// which may be a function of props and context 9 10providers.entry.replication = { 11 reducerKeys: ['time', 'author', 'entry', 'tags'], 12 replicator: rethink 13}; 14 15providers.comment.replication = { 16 reducerKeys: ['time', 'author', 'comment', 'for'], 17 replicator: rethink 18}; 19 20providers.message.replication = { 21 reducerKeys: ['time', 'author', 'message'], 22 replicator: socket 23};
compose
1import { createStore, combineReducers, compose } from 'redux'; 2import replicate from 'redux-replicate'; 3import localforage from 'redux-replicate-localforage'; 4import reducers from './reducers'; 5 6const initialState = { 7 wow: 'such storage', 8 very: 'cool' 9}; 10 11const key = 'superCoolStorageUnit'; 12const reducerKeys = true; 13const replicator = localforage; 14const replication = replicate({ key, reducerKeys, replicator }); 15const create = compose(replication)(createStore); 16const store = create(combineReducers(reducers), initialState);
No vulnerabilities found.
No security vulnerabilities found.