Преглед изворни кода

fix(frontend): Prevent from setting multiple terminal stdin listeners on re-renders (#5653)

sp.wack пре 1 година
родитељ
комит
8b1a7dff7e
1 измењених фајлова са 37 додато и 18 уклоњено
  1. 37 18
      frontend/src/hooks/use-terminal.ts

+ 37 - 18
frontend/src/hooks/use-terminal.ts

@@ -33,6 +33,7 @@ export const useTerminal = ({
   const fitAddon = React.useRef<FitAddon | null>(null);
   const ref = React.useRef<HTMLDivElement>(null);
   const lastCommandIndex = React.useRef(0);
+  const keyEventDisposable = React.useRef<{ dispose: () => void } | null>(null);
 
   const createTerminal = () =>
     new Terminal({
@@ -143,40 +144,58 @@ export const useTerminal = ({
 
   React.useEffect(() => {
     if (terminal.current) {
+      // Dispose of existing listeners if they exist
+      if (keyEventDisposable.current) {
+        keyEventDisposable.current.dispose();
+        keyEventDisposable.current = null;
+      }
+
       let commandBuffer = "";
 
       if (!disabled) {
-        terminal.current.onKey(({ key, domEvent }) => {
-          if (domEvent.key === "Enter") {
-            handleEnter(commandBuffer);
-            commandBuffer = "";
-          } else if (domEvent.key === "Backspace") {
-            if (commandBuffer.length > 0) {
-              commandBuffer = handleBackspace(commandBuffer);
-            }
-          } else {
-            // Ignore paste event
-            if (key.charCodeAt(0) === 22) {
-              return;
+        // Add new key event listener and store the disposable
+        keyEventDisposable.current = terminal.current.onKey(
+          ({ key, domEvent }) => {
+            if (domEvent.key === "Enter") {
+              handleEnter(commandBuffer);
+              commandBuffer = "";
+            } else if (domEvent.key === "Backspace") {
+              if (commandBuffer.length > 0) {
+                commandBuffer = handleBackspace(commandBuffer);
+              }
+            } else {
+              // Ignore paste event
+              if (key.charCodeAt(0) === 22) {
+                return;
+              }
+              commandBuffer += key;
+              terminal.current?.write(key);
             }
-            commandBuffer += key;
-            terminal.current?.write(key);
-          }
-        });
+          },
+        );
 
+        // Add custom key handler and store the disposable
         terminal.current.attachCustomKeyEventHandler((event) =>
           pasteHandler(event, (text) => {
             commandBuffer += text;
           }),
         );
       } else {
-        terminal.current.onKey((e) => {
+        // Add a noop handler when disabled
+        keyEventDisposable.current = terminal.current.onKey((e) => {
           e.domEvent.preventDefault();
           e.domEvent.stopPropagation();
         });
       }
     }
-  }, [disabled, terminal]);
+
+    return () => {
+      if (keyEventDisposable.current) {
+        keyEventDisposable.current.dispose();
+        keyEventDisposable.current = null;
+      }
+    };
+  }, [disabled]);
 
   return ref;
 };