fix: prevent SpeechRecognition instance leaks on render (#1369)

* fix: remove unstable dependencies from speech recognition effect

* fix: use refs to prevent stale closures in speech recognition

* Apply suggestions from code review

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
7. Sun
2026-03-28 08:20:38 +00:00
committed by GitHub
parent d22cab8614
commit 49f2e38fbf

View File

@@ -1128,6 +1128,8 @@ export const PromptInputSpeechButton = ({
null, null,
); );
const recognitionRef = useRef<SpeechRecognition | null>(null); const recognitionRef = useRef<SpeechRecognition | null>(null);
const callbacksRef = useRef({ textareaRef, onTranscriptionChange });
callbacksRef.current = { textareaRef, onTranscriptionChange };
useEffect(() => { useEffect(() => {
if ( if (
@@ -1160,15 +1162,18 @@ export const PromptInputSpeechButton = ({
} }
} }
if (finalTranscript && textareaRef?.current) { const currentTextareaRef = callbacksRef.current.textareaRef;
const textarea = textareaRef.current; const currentOnTranscriptionChange = callbacksRef.current.onTranscriptionChange;
if (finalTranscript && currentTextareaRef?.current) {
const textarea = currentTextareaRef.current;
const currentValue = textarea.value; const currentValue = textarea.value;
const newValue = const newValue =
currentValue + (currentValue ? " " : "") + finalTranscript; currentValue + (currentValue ? " " : "") + finalTranscript;
textarea.value = newValue; textarea.value = newValue;
textarea.dispatchEvent(new Event("input", { bubbles: true })); textarea.dispatchEvent(new Event("input", { bubbles: true }));
onTranscriptionChange?.(newValue); currentOnTranscriptionChange?.(newValue);
} }
}; };
@@ -1186,7 +1191,7 @@ export const PromptInputSpeechButton = ({
recognitionRef.current.stop(); recognitionRef.current.stop();
} }
}; };
}, [textareaRef, onTranscriptionChange]); }, []);
const toggleListening = useCallback(() => { const toggleListening = useCallback(() => {
if (!recognition) { if (!recognition) {