diff --git a/packages/insomnia/src/common/misc.ts b/packages/insomnia/src/common/misc.ts index dbd255c9c2..111760e4a5 100644 --- a/packages/insomnia/src/common/misc.ts +++ b/packages/insomnia/src/common/misc.ts @@ -109,6 +109,7 @@ export const debounce = ) => ReturnType>( clearTimeout(timeout); timeout = setTimeout(() => func(...args), waitFor); }; + debounced.cancel = () => clearTimeout(timeout); return debounced; }; diff --git a/packages/insomnia/src/ui/components/.client/codemirror/one-line-editor.tsx b/packages/insomnia/src/ui/components/.client/codemirror/one-line-editor.tsx index 0a30a2c3e3..d5e186a792 100644 --- a/packages/insomnia/src/ui/components/.client/codemirror/one-line-editor.tsx +++ b/packages/insomnia/src/ui/components/.client/codemirror/one-line-editor.tsx @@ -65,6 +65,8 @@ export const OneLineEditor = forwardRef ) => { const textAreaRef = useRef(null); const codeMirror = useRef(null); + const onChangeRef = useRef(onChange); + onChangeRef.current = onChange; const { settings } = useRootLoaderData()!; const { isOwner, isEnterprisePlan } = usePlanData(); const { handleRender, handleGetRenderContext } = useNunjucks(); @@ -296,23 +298,26 @@ export const OneLineEditor = forwardRef useEffect(() => { const fn = misc.debounce((doc: CodeMirror.Editor) => { - if (onChange) { - onChange(doc.getValue() || ''); + if (onChangeRef.current) { + onChangeRef.current(doc.getValue() || ''); } }, DEBOUNCE_MILLIS); - codeMirror.current?.on('changes', fn); - return () => codeMirror.current?.off('changes', fn); - }, [onChange]); - - useEffect(() => { const flushOnBlur = (doc: CodeMirror.Editor) => { - if (onChange) { - onChange(doc.getValue() || ''); + // Cancel the pending debounce so a stale fire can't overwrite state after blur + fn.cancel(); + if (onChangeRef.current) { + onChangeRef.current(doc.getValue() || ''); } }; + codeMirror.current?.on('changes', fn); codeMirror.current?.on('blur', flushOnBlur); - return () => codeMirror.current?.off('blur', flushOnBlur); - }, [onChange]); + return () => { + fn.cancel(); + codeMirror.current?.off('changes', fn); + codeMirror.current?.off('blur', flushOnBlur); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); useEffect(() => { const unsubscribe = window.main.on(