Open-source Project Lab / Project
Build undo and redo for a drawing tool
Model drawing history with immutable snapshots and test the branch after an undo.
You will learn to
- Run a useful project building block
- Test edge cases before adding a UI
- Explore a related open-source application
Before you start
JavaScript arrays and functions
Represent a drawing
For this exercise a drawing is a string, so the history behavior is easy to inspect. Past stores previous snapshots, present is the visible drawing, and future stores undone snapshots. Real drawings can use arrays of shapes with stable ids.
Explain a branch
Undo a square back to a circle, then draw a triangle. Redo must no longer restore the old square: that future belongs to an abandoned branch. Try this sequence in the editor and inspect the arrays. Avoid mutating previous snapshots or older history will change too.
Extend the project
Implement redo by moving the first future snapshot to present. Add a bounded history of fifty snapshots and test its oldest boundary. Explore Excalidraw to see a real drawing application; this companion is an original state-model exercise, not an embedded Excalidraw editor.
Try it yourself
function edit(history, next) {
return {past: [...history.past, history.present], present: next, future: []};
}
function undo(history) {
if (!history.past.length) return history;
return {past: history.past.slice(0,-1), present: history.past.at(-1), future: [history.present,...history.future]};
}
console.log(undo(edit({past:[],present:"circle",future:[]},"square")));Enable JavaScript for this interactive activity. You can read all lesson explanations above without it.