Simple utility to make reducers undoable.
undoable-reducer
provides simple utility to make any reducer undoable.
Here is a small demo.
As any other npm package undoable-reducer
can be added to your project by following command:
npm i -S undoable-reducer
To make any reducer undoable just pass it to makeUndoable()
function as 1st argument:
import makeUndoable from 'undoable-reducer';
const reducer = (state, action) => {
...
};
export default makeUndoable(reducer);
To use undo/redo functionality, undoable-reducer
exports action types for undo and redo actions:
import { TYPES } from 'undoable-reducer';
const Component = ({ dispatch }) => {
...
dispatch({ type: TYPES.undo });
};
undoable-reducer
exports action creators as well:
import { ACTIONS } from 'undoable-reducer';
const Component = ({ dispatch }) => {
...
dispatch(ACTIONS.undo());
};
To use undo/redo functionality across several reducers makeUndoable()
can be applied to combined reducer...
import makeUndoable from 'undoable-reducer';
import combineReducers from 'redux';
import theme from './theme';
import locale from './locale';
import editor from './locale';
// to add undo/redo functionality to whole state
export default makeUndoable(combineReducers({
theme, locale, editor
}));
or any specific reducer:
...
// to add undo/redo functionality editor state only
export default combineReducers({
theme, locale,
editor: makeUndoable(editor)
});
makeUndoable()
function can be configured using options
parameter.
In some cases we may want to use custom undo/redo actions. To do so we just need to pass undo and redo action types during makeUndoable()
call:
import { CUSTOM_UNDO as undo, CUSTOM_REDO as redo } from '../actions/editor';
export default makeUndoable(editorReducer, {
types: { undo, redo }
})
By doing so we can group several states under the same undo/redo history.
There is another option length
to set maximum history length for undoable reducer (which is 10 by default):
// use will be able to undo (and then redo) up to 20 times
export default makeUndoable(reducer, { length: 20 });