diff --git a/src/actions/actionCanvas.tsx b/src/actions/actionCanvas.tsx
index b5e54df9..182da736 100644
--- a/src/actions/actionCanvas.tsx
+++ b/src/actions/actionCanvas.tsx
@@ -14,7 +14,10 @@ import { newElementWith } from "../element/mutateElement";
 export const actionChangeViewBackgroundColor = register({
   name: "changeViewBackgroundColor",
   perform: (_, appState, value) => {
-    return { appState: { ...appState, viewBackgroundColor: value } };
+    return {
+      appState: { ...appState, viewBackgroundColor: value },
+      commitToHistory: true,
+    };
   },
   PanelComponent: ({ appState, updateData }) => {
     return (
@@ -28,18 +31,17 @@ export const actionChangeViewBackgroundColor = register({
       </div>
     );
   },
-  commitToHistory: () => true,
 });
 
 export const actionClearCanvas = register({
   name: "clearCanvas",
-  commitToHistory: () => true,
   perform: elements => {
     return {
       elements: elements.map(element =>
         newElementWith(element, { isDeleted: true }),
       ),
       appState: getDefaultAppState(),
+      commitToHistory: true,
     };
   },
   PanelComponent: ({ updateData }) => (
@@ -81,6 +83,7 @@ export const actionZoomIn = register({
         ...appState,
         zoom: getNormalizedZoom(appState.zoom + ZOOM_STEP),
       },
+      commitToHistory: false,
     };
   },
   PanelComponent: ({ updateData }) => (
@@ -107,6 +110,7 @@ export const actionZoomOut = register({
         ...appState,
         zoom: getNormalizedZoom(appState.zoom - ZOOM_STEP),
       },
+      commitToHistory: false,
     };
   },
   PanelComponent: ({ updateData }) => (
@@ -133,6 +137,7 @@ export const actionResetZoom = register({
         ...appState,
         zoom: 1,
       },
+      commitToHistory: false,
     };
   },
   PanelComponent: ({ updateData }) => (
diff --git a/src/actions/actionDeleteSelected.tsx b/src/actions/actionDeleteSelected.tsx
index e8979274..dcf84341 100644
--- a/src/actions/actionDeleteSelected.tsx
+++ b/src/actions/actionDeleteSelected.tsx
@@ -20,12 +20,11 @@ export const actionDeleteSelected = register({
         elementType: "selection",
         multiElement: null,
       },
+      commitToHistory: isSomeElementSelected(elements, appState),
     };
   },
   contextItemLabel: "labels.delete",
   contextMenuOrder: 3,
-  commitToHistory: (appState, elements) =>
-    isSomeElementSelected(elements, appState),
   keyTest: event => event.key === KEYS.BACKSPACE || event.key === KEYS.DELETE,
   PanelComponent: ({ elements, appState, updateData }) => (
     <ToolButton
diff --git a/src/actions/actionDuplicateSelection.ts b/src/actions/actionDuplicateSelection.ts
index b993df2e..5c057fa1 100644
--- a/src/actions/actionDuplicateSelection.ts
+++ b/src/actions/actionDuplicateSelection.ts
@@ -23,6 +23,7 @@ export const actionDuplicateSelection = register({
         },
         [],
       ),
+      commitToHistory: true,
     };
   },
   contextItemLabel: "labels.duplicateSelection",
diff --git a/src/actions/actionExport.tsx b/src/actions/actionExport.tsx
index 59c4d3db..d790e81f 100644
--- a/src/actions/actionExport.tsx
+++ b/src/actions/actionExport.tsx
@@ -10,7 +10,7 @@ import { register } from "./register";
 export const actionChangeProjectName = register({
   name: "changeProjectName",
   perform: (_elements, appState, value) => {
-    return { appState: { ...appState, name: value } };
+    return { appState: { ...appState, name: value }, commitToHistory: false };
   },
   PanelComponent: ({ appState, updateData }) => (
     <ProjectName
@@ -24,7 +24,10 @@ export const actionChangeProjectName = register({
 export const actionChangeExportBackground = register({
   name: "changeExportBackground",
   perform: (_elements, appState, value) => {
-    return { appState: { ...appState, exportBackground: value } };
+    return {
+      appState: { ...appState, exportBackground: value },
+      commitToHistory: false,
+    };
   },
   PanelComponent: ({ appState, updateData }) => (
     <label>
@@ -42,7 +45,7 @@ export const actionSaveScene = register({
   name: "saveScene",
   perform: (elements, appState, value) => {
     saveAsJSON(elements, appState).catch(error => console.error(error));
-    return {};
+    return { commitToHistory: false };
   },
   PanelComponent: ({ updateData }) => (
     <ToolButton
@@ -63,7 +66,11 @@ export const actionLoadScene = register({
     appState,
     { elements: loadedElements, appState: loadedAppState },
   ) => {
-    return { elements: loadedElements, appState: loadedAppState };
+    return {
+      elements: loadedElements,
+      appState: loadedAppState,
+      commitToHistory: false,
+    };
   },
   PanelComponent: ({ updateData }) => (
     <ToolButton
diff --git a/src/actions/actionFinalize.tsx b/src/actions/actionFinalize.tsx
index 46d0eef8..7ec7c434 100644
--- a/src/actions/actionFinalize.tsx
+++ b/src/actions/actionFinalize.tsx
@@ -52,6 +52,7 @@ export const actionFinalize = register({
         editingElement: null,
         selectedElementIds: {},
       },
+      commitToHistory: false,
     };
   },
   keyTest: (event, appState) =>
diff --git a/src/actions/actionHistory.tsx b/src/actions/actionHistory.tsx
index b5d818d6..1fcdeda3 100644
--- a/src/actions/actionHistory.tsx
+++ b/src/actions/actionHistory.tsx
@@ -1,4 +1,4 @@
-import { Action } from "./types";
+import { Action, ActionResult } from "./types";
 import React from "react";
 import { undo, redo } from "../components/icons";
 import { ToolButton } from "../components/ToolButton";
@@ -13,8 +13,12 @@ import { newElementWith } from "../element/mutateElement";
 const writeData = (
   prevElements: readonly ExcalidrawElement[],
   appState: AppState,
-  updater: () => { elements: ExcalidrawElement[]; appState: AppState } | null,
-) => {
+  updater: () => {
+    elements: ExcalidrawElement[];
+    appState: AppState;
+  } | null,
+): ActionResult => {
+  const commitToHistory = false;
   if (
     !appState.multiElement &&
     !appState.resizingElement &&
@@ -23,7 +27,7 @@ const writeData = (
   ) {
     const data = updater();
     if (data === null) {
-      return {};
+      return { commitToHistory };
     }
 
     const prevElementMap = getElementMap(prevElements);
@@ -47,9 +51,10 @@ const writeData = (
             ),
         ),
       appState: { ...appState, ...data.appState },
+      commitToHistory,
     };
   }
-  return {};
+  return { commitToHistory };
 };
 
 const testUndo = (shift: boolean) => (event: KeyboardEvent) =>
diff --git a/src/actions/actionMenu.tsx b/src/actions/actionMenu.tsx
index dcbfb512..3db133e6 100644
--- a/src/actions/actionMenu.tsx
+++ b/src/actions/actionMenu.tsx
@@ -12,6 +12,7 @@ export const actionToggleCanvasMenu = register({
       ...appState,
       openMenu: appState.openMenu === "canvas" ? null : "canvas",
     },
+    commitToHistory: false,
   }),
   PanelComponent: ({ appState, updateData }) => (
     <ToolButton
@@ -31,6 +32,7 @@ export const actionToggleEditMenu = register({
       ...appState,
       openMenu: appState.openMenu === "shape" ? null : "shape",
     },
+    commitToHistory: false,
   }),
   PanelComponent: ({ elements, appState, updateData }) => (
     <ToolButton
diff --git a/src/actions/actionProperties.tsx b/src/actions/actionProperties.tsx
index 0781d991..c67c1640 100644
--- a/src/actions/actionProperties.tsx
+++ b/src/actions/actionProperties.tsx
@@ -52,9 +52,9 @@ export const actionChangeStrokeColor = register({
         }),
       ),
       appState: { ...appState, currentItemStrokeColor: value },
+      commitToHistory: true,
     };
   },
-  commitToHistory: () => true,
   PanelComponent: ({ elements, appState, updateData }) => (
     <>
       <h3 aria-hidden="true">{t("labels.stroke")}</h3>
@@ -83,9 +83,9 @@ export const actionChangeBackgroundColor = register({
         }),
       ),
       appState: { ...appState, currentItemBackgroundColor: value },
+      commitToHistory: true,
     };
   },
-  commitToHistory: () => true,
   PanelComponent: ({ elements, appState, updateData }) => (
     <>
       <h3 aria-hidden="true">{t("labels.background")}</h3>
@@ -114,9 +114,9 @@ export const actionChangeFillStyle = register({
         }),
       ),
       appState: { ...appState, currentItemFillStyle: value },
+      commitToHistory: true,
     };
   },
-  commitToHistory: () => true,
   PanelComponent: ({ elements, appState, updateData }) => (
     <fieldset>
       <legend>{t("labels.fill")}</legend>
@@ -151,9 +151,9 @@ export const actionChangeStrokeWidth = register({
         }),
       ),
       appState: { ...appState, currentItemStrokeWidth: value },
+      commitToHistory: true,
     };
   },
-  commitToHistory: () => true,
   PanelComponent: ({ elements, appState, updateData }) => (
     <fieldset>
       <legend>{t("labels.strokeWidth")}</legend>
@@ -186,9 +186,9 @@ export const actionChangeSloppiness = register({
         }),
       ),
       appState: { ...appState, currentItemRoughness: value },
+      commitToHistory: true,
     };
   },
-  commitToHistory: () => true,
   PanelComponent: ({ elements, appState, updateData }) => (
     <fieldset>
       <legend>{t("labels.sloppiness")}</legend>
@@ -221,9 +221,9 @@ export const actionChangeOpacity = register({
         }),
       ),
       appState: { ...appState, currentItemOpacity: value },
+      commitToHistory: true,
     };
   },
-  commitToHistory: () => true,
   PanelComponent: ({ elements, appState, updateData }) => (
     <label className="control-label">
       {t("labels.opacity")}
@@ -281,9 +281,9 @@ export const actionChangeFontSize = register({
           appState.currentItemFont.split("px ")[1]
         }`,
       },
+      commitToHistory: true,
     };
   },
-  commitToHistory: () => true,
   PanelComponent: ({ elements, appState, updateData }) => (
     <fieldset>
       <legend>{t("labels.fontSize")}</legend>
@@ -328,9 +328,9 @@ export const actionChangeFontFamily = register({
           appState.currentItemFont.split("px ")[0]
         }px ${value}`,
       },
+      commitToHistory: true,
     };
   },
-  commitToHistory: () => true,
   PanelComponent: ({ elements, appState, updateData }) => (
     <fieldset>
       <legend>{t("labels.fontFamily")}</legend>
diff --git a/src/actions/actionSelectAll.ts b/src/actions/actionSelectAll.ts
index b2f0e7ca..6ccfd9a8 100644
--- a/src/actions/actionSelectAll.ts
+++ b/src/actions/actionSelectAll.ts
@@ -12,6 +12,7 @@ export const actionSelectAll = register({
           return map;
         }, {} as any),
       },
+      commitToHistory: true,
     };
   },
   contextItemLabel: "labels.selectAll",
diff --git a/src/actions/actionStyles.ts b/src/actions/actionStyles.ts
index e66f4179..fb1f431f 100644
--- a/src/actions/actionStyles.ts
+++ b/src/actions/actionStyles.ts
@@ -17,7 +17,9 @@ export const actionCopyStyles = register({
     if (element) {
       copiedStyles = JSON.stringify(element);
     }
-    return {};
+    return {
+      commitToHistory: false,
+    };
   },
   contextItemLabel: "labels.copyStyles",
   keyTest: event =>
@@ -30,7 +32,7 @@ export const actionPasteStyles = register({
   perform: (elements, appState) => {
     const pastedElement = JSON.parse(copiedStyles);
     if (!isExcalidrawElement(pastedElement)) {
-      return { elements };
+      return { elements, commitToHistory: false };
     }
     return {
       elements: elements.map(element => {
@@ -53,9 +55,9 @@ export const actionPasteStyles = register({
         }
         return element;
       }),
+      commitToHistory: true,
     };
   },
-  commitToHistory: () => true,
   contextItemLabel: "labels.pasteStyles",
   keyTest: event =>
     event[KEYS.CTRL_OR_CMD] && event.shiftKey && event.key === "V",
diff --git a/src/actions/actionZindex.tsx b/src/actions/actionZindex.tsx
index 21eeb6d1..5a481ab3 100644
--- a/src/actions/actionZindex.tsx
+++ b/src/actions/actionZindex.tsx
@@ -26,11 +26,11 @@ export const actionSendBackward = register({
         getSelectedIndices(elements, appState),
       ),
       appState,
+      commitToHistory: true,
     };
   },
   contextItemLabel: "labels.sendBackward",
   keyPriority: 40,
-  commitToHistory: () => true,
   keyTest: event =>
     event[KEYS.CTRL_OR_CMD] && !event.shiftKey && event.code === "BracketLeft",
   PanelComponent: ({ updateData }) => (
@@ -54,11 +54,11 @@ export const actionBringForward = register({
         getSelectedIndices(elements, appState),
       ),
       appState,
+      commitToHistory: true,
     };
   },
   contextItemLabel: "labels.bringForward",
   keyPriority: 40,
-  commitToHistory: () => true,
   keyTest: event =>
     event[KEYS.CTRL_OR_CMD] && !event.shiftKey && event.code === "BracketRight",
   PanelComponent: ({ updateData }) => (
@@ -82,10 +82,10 @@ export const actionSendToBack = register({
         getSelectedIndices(elements, appState),
       ),
       appState,
+      commitToHistory: true,
     };
   },
   contextItemLabel: "labels.sendToBack",
-  commitToHistory: () => true,
   keyTest: event => {
     return isDarwin
       ? event[KEYS.CTRL_OR_CMD] && event.altKey && event.code === "BracketLeft"
@@ -118,9 +118,9 @@ export const actionBringToFront = register({
         getSelectedIndices(elements, appState),
       ),
       appState,
+      commitToHistory: true,
     };
   },
-  commitToHistory: () => true,
   contextItemLabel: "labels.bringToFront",
   keyTest: event => {
     return isDarwin
diff --git a/src/actions/manager.tsx b/src/actions/manager.tsx
index 00a09a66..e085cd9d 100644
--- a/src/actions/manager.tsx
+++ b/src/actions/manager.tsx
@@ -50,24 +50,12 @@ export class ActionManager implements ActionsManagerInterface {
     }
 
     event.preventDefault();
-    const commitToHistory =
-      data[0].commitToHistory &&
-      data[0].commitToHistory(this.getAppState(), this.getElements());
-    this.updater(
-      data[0].perform(this.getElements(), this.getAppState(), null),
-      commitToHistory,
-    );
+    this.updater(data[0].perform(this.getElements(), this.getAppState(), null));
     return true;
   }
 
   executeAction(action: Action) {
-    const commitToHistory =
-      action.commitToHistory &&
-      action.commitToHistory(this.getAppState(), this.getElements());
-    this.updater(
-      action.perform(this.getElements(), this.getAppState(), null),
-      commitToHistory,
-    );
+    this.updater(action.perform(this.getElements(), this.getAppState(), null));
   }
 
   getContextMenuItems(actionFilter: ActionFilterFn = action => action) {
@@ -82,12 +70,8 @@ export class ActionManager implements ActionsManagerInterface {
       .map(action => ({
         label: action.contextItemLabel ? t(action.contextItemLabel) : "",
         action: () => {
-          const commitToHistory =
-            action.commitToHistory &&
-            action.commitToHistory(this.getAppState(), this.getElements());
           this.updater(
             action.perform(this.getElements(), this.getAppState(), null),
-            commitToHistory,
           );
         },
       }));
@@ -98,12 +82,8 @@ export class ActionManager implements ActionsManagerInterface {
       const action = this.actions[name];
       const PanelComponent = action.PanelComponent!;
       const updateData = (formState?: any) => {
-        const commitToHistory =
-          action.commitToHistory &&
-          action.commitToHistory(this.getAppState(), this.getElements());
         this.updater(
           action.perform(this.getElements(), this.getAppState(), formState),
-          commitToHistory,
         );
       };
 
diff --git a/src/actions/types.ts b/src/actions/types.ts
index c1fe7251..609c9c2b 100644
--- a/src/actions/types.ts
+++ b/src/actions/types.ts
@@ -5,6 +5,7 @@ import { AppState } from "../types";
 export type ActionResult = {
   elements?: readonly ExcalidrawElement[] | null;
   appState?: AppState | null;
+  commitToHistory: boolean;
 };
 
 type ActionFn = (
@@ -32,10 +33,6 @@ export interface Action {
   ) => boolean;
   contextItemLabel?: string;
   contextMenuOrder?: number;
-  commitToHistory?: (
-    appState: AppState,
-    elements: readonly ExcalidrawElement[],
-  ) => boolean;
 }
 
 export interface ActionsManagerInterface {
diff --git a/src/components/App.tsx b/src/components/App.tsx
index 89cf76ec..228d0afe 100644
--- a/src/components/App.tsx
+++ b/src/components/App.tsx
@@ -105,11 +105,14 @@ import { isLinearElement } from "../element/typeChecks";
 import { rescalePoints } from "../points";
 import { actionFinalize } from "../actions";
 
+/**
+ * @param func handler taking at most single parameter (event).
+ */
 function withBatchedUpdates<
   TFunction extends ((event: any) => void) | (() => void)
->(func: TFunction) {
+>(func: Parameters<TFunction>["length"] extends 0 | 1 ? TFunction : never) {
   return (event => {
-    unstable_batchedUpdates(func, event);
+    unstable_batchedUpdates(func as TFunction, event);
   }) as TFunction;
 }
 
@@ -164,30 +167,28 @@ export class App extends React.Component<any, AppState> {
     this.actionManager.registerAction(createRedoAction(history));
   }
 
-  private syncActionResult = withBatchedUpdates(
-    (res: ActionResult, commitToHistory: boolean = true) => {
-      if (this.unmounted) {
-        return;
-      }
-      if (res.elements) {
-        globalSceneState.replaceAllElements(res.elements);
-        if (commitToHistory) {
-          history.resumeRecording();
-        }
+  private syncActionResult = withBatchedUpdates((res: ActionResult) => {
+    if (this.unmounted) {
+      return;
+    }
+    if (res.elements) {
+      globalSceneState.replaceAllElements(res.elements);
+      if (res.commitToHistory) {
+        history.resumeRecording();
       }
+    }
 
-      if (res.appState) {
-        if (commitToHistory) {
-          history.resumeRecording();
-        }
-        this.setState(state => ({
-          ...res.appState,
-          isCollaborating: state.isCollaborating,
-          collaborators: state.collaborators,
-        }));
+    if (res.appState) {
+      if (res.commitToHistory) {
+        history.resumeRecording();
       }
-    },
-  );
+      this.setState(state => ({
+        ...res.appState,
+        isCollaborating: state.isCollaborating,
+        collaborators: state.collaborators,
+      }));
+    }
+  });
 
   private onCut = withBatchedUpdates((event: ClipboardEvent) => {
     if (isWritableElement(event.target)) {
@@ -635,7 +636,8 @@ export class App extends React.Component<any, AppState> {
       } else if (event.key === "q") {
         this.toggleLock();
       }
-    } else if (event.key === KEYS.SPACE && gesture.pointers.size === 0) {
+    }
+    if (event.key === KEYS.SPACE && gesture.pointers.size === 0) {
       isHoldingSpace = true;
       document.documentElement.style.cursor = CURSOR_TYPE.GRABBING;
     }
@@ -917,7 +919,11 @@ export class App extends React.Component<any, AppState> {
               ) {
                 loadFromBlob(file)
                   .then(({ elements, appState }) =>
-                    this.syncActionResult({ elements, appState }),
+                    this.syncActionResult({
+                      elements,
+                      appState,
+                      commitToHistory: false,
+                    }),
                   )
                   .catch(error => console.error(error));
               }
diff --git a/src/data/index.ts b/src/data/index.ts
index b4b5ce0e..1b97a5df 100644
--- a/src/data/index.ts
+++ b/src/data/index.ts
@@ -357,5 +357,6 @@ export async function loadScene(id: string | null, privateKey?: string) {
   return {
     elements: data.elements,
     appState: data.appState && { ...data.appState },
+    commitToHistory: false,
   };
 }
diff --git a/src/history.ts b/src/history.ts
index 925d096a..f12f5231 100644
--- a/src/history.ts
+++ b/src/history.ts
@@ -83,7 +83,7 @@ export class SceneHistory {
   }
 
   undoOnce(): Result | null {
-    if (this.stateHistory.length === 0) {
+    if (this.stateHistory.length === 1) {
       return null;
     }