This package will make your redux store undoable.
- Support for making only a slice of the state undoable
- more examples and documentation
define the dependency in your pubspec.yaml
file:
dependencies:
redux_undo: ^1.0.0+1
update your applications packages by running
pub get
or when using flutter as a framework
flutter pub get
import the package to use in the file you are setting up redux:
import 'package:redux_undo/redux_undo.dart';
redux_undo
will slightly modify your state by adding a new properties-layer at the root of the store. The final structure will look like this:
/// when accessed directly from the store, store.state will have this structure
UndoableHistory<S> state = {
past: <S>[],
present: null, // <-- the current state of the app
future: <S>[],
latestUnfiltered: null // <-- basically equals present, to store a mutual state before storing it into past or future
};
Because it modifies the initial state you need to initiate redux_undo
when initiating the redux store.
This is done by calling 2 separate functions:
/// to wrap the root reducer
Reducer<UndoableState<S>> createUndoableReducer<S>(Reducer<S> reducer, { UndoableConfig config });
/// to wrap the Root state of your app.
UndoableState<S> createUndoableState<S>(S initialState, bool ignoreInitialState);
Here is an example of how this can be done in a flutter app:
import 'package:flutter/material.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';
import 'package:redux_undo/redux_undo.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
final Store<UndoableState<RootState>> store = Store<UndoableState<RootState>>(
createUndoableReducer<RootState>(rootReducer),
initialState: createUndoableState(RootState.initial(), false),
);
@override
Widget build(BuildContext context) {
return StoreProvider<UndoableState<RootState>>(
store: store,
child: MaterialApp(
title: 'Redux Undo Demo',
home: const MyHomePage(),
),
);
}
}
redux_undo
provides 4 basic actions
-
UndoableUndoAction
- Standard-Action for undoUsage:
store.dispatch(UndoableUndoAction())
-
UndoableRedoAction
- Standard-Action for redoUsage:
store.dispatch(UndoableRedoAction())
-
UndoableJumpAction
- Standard-Action for jump (to past or to future)Usage:
store.dispatch(UndoableJumpAction(index: -2))
// <- jumps 2 steps to the past (same as dispatchingUndoableUndoAction
twice)Usage:
store.dispatch(UndoableJumpAction(index: 0))
// <- does nothing, since it just returns the currentUndoableState
Usage:
store.dispatch(UndoableJumpAction(index: 2))
// <- jumps 2 steps to the future (same as dispatchingUndoableRedoAction
twice) -
UndoableClearHistoryAction
- Standard-Action for clearing the history
It is possible to provide a configuration object to the UndoableState instantiation like this:
final UndoableConfig config = UndoableConfig(
limit: 100,
blackList: <Type>[
BlacklistedAction,
],
whiteList: <Type>[
WhitelistedAction,
],
);
Then pass it to the createUndoableReducer
function like this:
final Store<UndoableState<RootState>> store = Store<UndoableState<RootState>>(
createUndoableReducer<RootState>(rootReducer, config: config),
initialState: createUndoableState(RootState.initial(), false),
);
These are the options the UndoableConfig
class provides:
- int limit: limits the length of the
UndoableState.past
List and with this ultimately the length ofUndoableState.future
as well- default value => 10
- List whiteList: actions in this list need to be extended from one of the provided
redux_undo
actions and will fire the originalrootReducer
after performing the action they extended from without updatingUndoableState.past
orUndoableState.future