@goco/redux-undo
v0.9.99
Published
simple undo/redo functionality for redux state containers
Downloads
4
Readme
redux undo/redo
simple undo/redo functionality for redux state containers
Protip: You can use the redux-undo-boilerplate to quickly get started with redux-undo
.
Note: Make sure to update your programs to the latest History API.
Installation
npm install --save redux-undo
API
import undoable from 'redux-undo';
undoable(reducer)
undoable(reducer, config)
Making your reducers undoable
redux-undo
is a reducer enhancer, it provides the undoable
function, which
takes an existing reducer and a configuration object and enhances your existing
reducer with undo functionality.
Note: If you were accessing state.counter
before, you have to access
state.counter.present
after wrapping your reducer with undoable
.
To install, firstly import redux-undo
:
// Redux utility functions
import { combineReducers } from 'redux';
// redux-undo higher-order reducer
import undoable from 'redux-undo';
Then, add undoable
to your reducer(s) like this:
combineReducers({
counter: undoable(counter)
})
A configuration can be passed like this:
combineReducers({
counter: undoable(counter, {
limit: 10 // set a limit for the history
})
})
History API
Wrapping your reducer with undoable
makes the state look like this:
{
past: [...pastStatesHere...],
present: {...currentStateHere...},
future: [...futureStatesHere...]
}
Now you can get your current state like this: state.present
And you can access all past states (e.g. to show a history) like this: state.past
Undo/Redo Actions
Firstly, import the undo/redo action creators:
import { ActionCreators } from 'redux-undo';
Then, you can use store.dispatch()
and the undo/redo action creators to
perform undo/redo operations on your state:
store.dispatch(ActionCreators.undo()) // undo the last action
store.dispatch(ActionCreators.redo()) // redo the last action
store.dispatch(ActionCreators.jumpToPast(index)) // jump to requested index in the past[] array
store.dispatch(ActionCreators.jumpToFuture(index)) // jump to requested index in the future[] array
Configuration
A configuration object can be passed to undoable()
like this (values shown
are default values):
undoable(reducer, {
limit: false, // set to a number to turn on a limit for the history
filter: () => true, // see `Filtering Actions` section
undoType: ActionTypes.UNDO, // define a custom action type for this undo action
redoType: ActionTypes.REDO, // define a custom action type for this redo action
jumpToPastType: ActionTypes.JUMP_TO_PAST, // define custom action type for this jumpToPast action
jumpToFutureType: ActionTypes.JUMP_TO_FUTURE, // define custom action type for this jumpToFuture action
initialState: undefined, // initial state (e.g. for loading)
initTypes: ['@@redux/INIT', '@@INIT'] // history will be (re)set upon init action type
initialHistory: { // initial history (e.g. for loading)
past: [],
present: config.initialState,
future: []
},
debug: false, // set to `true` to turn on debugging
})
Filtering Actions
If you don't want to include every action in the undo/redo history, you can
pass a function to undoable
like this:
undoable(reducer, function filterActions(action, currentState, previousState) {
return action.type === SOME_ACTION; // only add to history if action is SOME_ACTION
})
// or you could do...
undoable(reducer, function filterState(action, currentState, previousState) {
return currentState !== previousState; // only add to history if state changed
})
Or you can use the distinctState
, includeAction
and excludeAction
helpers,
which should be imported like this:
import undoable, { distinctState, includeAction, excludeAction } from 'redux-undo';
Now you can use the helper, which is pretty simple:
undoable(reducer, { filter: includeAction(SOME_ACTION) })
undoable(reducer, { filter: excludeAction(SOME_ACTION) })
// or you could do...
undoable(reducer, { filter: distinctState() })
... they even support Arrays:
undoable(reducer, { filter: includeAction([SOME_ACTION, SOME_OTHER_ACTION]) })
undoable(reducer, { filter: excludeAction([SOME_ACTION, SOME_OTHER_ACTION]) })
What is this magic? How does it work?
Have a read of the Implementing Undo History recipe in the Redux documents, which explains in detail how redux-undo works.
License
MIT, see LICENSE.md
for more information.