From da4948741e337c78302c35621bbdb52afd95191b Mon Sep 17 00:00:00 2001 From: ruinivist <179396038+ruinivist@users.noreply.github.com> Date: Sat, 6 Jun 2026 07:54:45 +0000 Subject: [PATCH] perf: strictly memoize Excalidraw callbacks to prevent unnecessary re-renders --- .jules/bolt.md | 4 ++++ src/client/App.tsx | 8 +++++--- src/client/components/EditorCanvas.tsx | 24 ++++++++++++++++-------- 3 files changed, 25 insertions(+), 11 deletions(-) create mode 100644 .jules/bolt.md diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000..4cb965d --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,4 @@ +## 2023-10-27 - Excalidraw Component Re-render Performance Penalty + +**Learning:** Due to the exceptionally high rendering cost of the `@excalidraw/excalidraw` canvas, inline functions passed as props (like `onChange` and `onExcalidrawAPI`) cause severe performance degradation by defeating `React.memo` and triggering full canvas re-renders when parent state changes. +**Action:** Always strictly memoize all callbacks passed to the Excalidraw component using `useCallback` to preserve prop stability and prevent unnecessary, expensive re-renders. diff --git a/src/client/App.tsx b/src/client/App.tsx index 33ddb41..5fd06e8 100644 --- a/src/client/App.tsx +++ b/src/client/App.tsx @@ -307,6 +307,10 @@ function PrivateApp() { [], ); + const handleExcalidrawAPI = useCallback((api: ExcalidrawImperativeAPI) => { + excalidrawApiRef.current = api; + }, []); + return (