diff --git a/services/web/frontend/js/features/pdf-preview/util/compiler.ts b/services/web/frontend/js/features/pdf-preview/util/compiler.ts index bd9eef3a40..27a5f3780d 100644 --- a/services/web/frontend/js/features/pdf-preview/util/compiler.ts +++ b/services/web/frontend/js/features/pdf-preview/util/compiler.ts @@ -119,9 +119,8 @@ export default class DocumentCompiler { this.setCompiling(true) if (wasCompiling) { - if (options.isAutoCompileOnChange) { - this.debouncedAutoCompile() - } + // The auto-compile effect in local-compile-context re-arms the debounce + // once compiling flips back to false, so we don't re-queue here. return } diff --git a/services/web/frontend/js/shared/context/local-compile-context.tsx b/services/web/frontend/js/shared/context/local-compile-context.tsx index 2ef1f08153..3bf7977af0 100644 --- a/services/web/frontend/js/shared/context/local-compile-context.tsx +++ b/services/web/frontend/js/shared/context/local-compile-context.tsx @@ -696,16 +696,20 @@ export const LocalCompileProvider: FC = ({ // show that the project has pending changes const hasChanges = Boolean(canAutoCompile && uncompiled && compiledOnce) - // call the debounced autocompile function if the project is available for auto-compiling and it has changed + // Trigger a debounced auto-compile when the project has changed. + // Crucially: cancel the debounce while a compile is already in flight so + // compiles don't chain back-to-back. When the compile finishes (compiling + // flips to false) and there are still uncompiled changes, the effect re-runs + // and re-arms the debounce exactly once. useEffect(() => { - if (canAutoCompile) { + if (canAutoCompile && !compiling) { if (changedAt > 0) { compiler.debouncedAutoCompile() } } else { compiler.debouncedAutoCompile.cancel() } - }, [compiler, canAutoCompile, changedAt]) + }, [compiler, canAutoCompile, changedAt, compiling]) // cancel debounced recompile on unmount useEffect(() => {