Skip to content

Instantly share code, notes, and snippets.

@kigawas
Last active December 28, 2020 07:50
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 kigawas/237415a4f7b7eda95f9de176e2434387 to your computer and use it in GitHub Desktop.
Save kigawas/237415a4f7b7eda95f9de176e2434387 to your computer and use it in GitHub Desktop.
redux in 40 lines of code with redo/undo
const createStore = (reducer) => {
const states = [reducer()];
let sp = 0; // stack pointer
const listeners = new Set();
function notify() {
for (const listener of listeners) {
listener();
}
}
function max(a, b) {
return a > b ? a : b;
}
function min(a, b) {
return a < b ? a : b;
}
return {
getState() {
return states[sp];
},
redo() {
sp = min(sp + 1, states.length - 1);
notify();
},
undo() {
sp = max(sp - 1, 0);
notify();
},
dispatch(action) {
const newState = reducer(this.getState(), action);
sp += 1;
if (sp === states.length) {
states.push(newState);
} else {
states[sp] = newState;
}
notify();
},
subscribe(listener) {
listeners.add(listener);
},
};
};
const countStore = createStore((state = { count: 0 }, action = { type: "" }) => {
switch (action.type) {
case "INCREASE_COUNT":
return { count: state.count + action.count };
default:
return state;
}
});
countStore.subscribe(() => {
// handler A
const { count } = countStore.getState();
console.log("A count:", count);
});
countStore.subscribe(() => {
// handler B
const { count } = countStore.getState();
console.log("B count:", count);
});
const increase = (n) => {
console.log("increase:", n);
countStore.dispatch({ type: "INCREASE_COUNT", count: n });
};
const undo = () => {
console.log("undo:");
countStore.undo();
}
const redo = () => {
console.log("redo:");
countStore.redo();
}
increase(1);
increase(3);
undo();
redo();
redo();
increase(-1);
increase(-3);
undo();
increase(1);
redo();
increase(3);
undo();
undo();
undo();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment