Skip to content

Instantly share code, notes, and snippets.

@praveen001
Created January 9, 2020 19:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save praveen001/ea2e4c64d260ed57cd0e3a4bd8b67819 to your computer and use it in GitHub Desktop.
Save praveen001/ea2e4c64d260ed57cd0e3a4bd8b67819 to your computer and use it in GitHub Desktop.
Undo/Redo with Immer in Redux
import { ADD_TODO, REMOVE_TODO } from '../actions/todos';
const changes = {};
let currentVersion = -1;
const noOfVersionsSupported = 100;
const undoableActions = [ADD_TODO, REMOVE_TODO];
export default function(state = initialState, action) {
return produce(state, draft => {
// ... code removed for brevity
}, (patches, inversePatches) => {
if (undoableActions.indexOf(action.type) !== -1) {
currentVersion++;
changes[currentVersion] = {
redo: patches,
undo: inversePatches
}
delete changes[currentVersion + 1];
delete changes[currentVersion - noOfVersionsSupported];
}
});
}
let state = {
name: "Micheal",
age: 32
};
state = produce(state, draft => {
draft.age = 40;
});
state = produce(state, draft => {
draft.age = 40;
}, (patches, inversePatches) => {
console.log(patches);
// [ { op: 'replace', path: [ 'age' ], value: 40 } ]
console.log(inversePatches);
// [ { op: 'replace', path: [ 'age' ], value: 32 } ]
});
import produce from 'immer';
import { ADD_TODO, REMOVE_TODO } from '../actions/todos';
const initialState = {
todos: [
{
desc: "Writing an article"
},
{
desc: "Dont use todo application for example"
}
]
}
export default function(state = initialState, action) {
return produce(state, draft => {
switch (action.type) {
case ADD_TODO:
draft.todos.push(action.payload.todo);
break;
case REMOVE_TODO:
draft.todos.splice(action.payload.index, 1);
break;
}
});
}
const changes = {};
let currentVersion = -1;
export default function(state = initialState, action) {
return produce(state, draft => {
// ... code removed for brevity
}, (patches, inversePatches) => {
currentVersion++;
changes[currentVersion] = {
redo: patches,
undo: inversePatches
}
});
}
const changes = {};
let currentVersion = -1;
const noOfVersionsSupported = 100;
export default function(state = initialState, action) {
return produce(state, draft => {
// ... code removed for brevity
}, (patches, inversePatches) => {
currentVersion++;
changes[currentVersion] = {
redo: patches,
undo: inversePatches
}
delete changes[currentVersion + 1];
delete changes[currentVersion - noOfVersionsSupported];
});
}
import produce, { applyPatches } from 'immer';
import { ADD_TODO, REMOVE_TODO, UNDO, REDO } from '../actions/todos';
// ... code removed for brevity
export default function(state = initialState, action) {
return produce(state, draft => {
switch (action.type) {
// ... code removed for brevity
case UNDO:
return applyPatches(state, changes[currentVersion--].undo);
case REDO:
return applyPatches(state, changes[++currentVersion].redo);
}
}, (patches, inversePatches) => {
// ... code removed for brevity
});
}
export default function(state = initialState, action) {
return produce(state, draft => {
switch (action.type) {
// ... code removed for brevity
case UNDO:
return produce(
applyPatches(state, changes[currentVersion--].undo),
newDraft => {
newDraft.canUndo = changes.hasOwnProperty(currentVersion);
newDraft.canRedo = true;
}
);
case REDO:
return produce(
applyPatches(state, changes[++currentVersion].redo),
newDraft => {
newDraft.canUndo = true;
newDraft.canRedo = changes.hasOwnProperty(currentVersion + 1);
}
);
}
if (undoableActions.indexOf(action.type) !== -1) {
draft.canUndo = true;
draft.canRedo = false;
}
}, (patches, inversePatches) => {
// ... code removed for brevity
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment