From 0138e4659e6bacf730c75a905815b6c8ed842041 Mon Sep 17 00:00:00 2001 From: ajnart Date: Mon, 6 Jul 2026 03:00:32 +0200 Subject: [PATCH] fix(forms): stabilize AppForm initialize effect deps to fix edit page render loop The useEffect that re-initializes the form when initialValues change had `form` in its dependency array. Mantine's useForm returns a fresh form object literal on every render, so the effect re-ran every render. The outer form.initialize() wrapper always calls handleValuesChanges() -> $errors.clearErrors() -> setErrorsState({}) (a new object), which triggers a re-render and loops infinitely. The resulting "Maximum update depth exceeded" error swallows all interactions, including sidebar link clicks, so router.push is interrupted and Next.js reports "navigation was cancelled" (issue #6198). initialValuesKey is a primitive string built from the initialValues fields, so it already covers the only case the effect exists for: re-initializing when initialValues actually changes (e.g. navigating between edit pages). Reported on v1.69.0/1.69.1, Edge and Chromium. --- packages/forms-collection/src/new-app/_form.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/forms-collection/src/new-app/_form.tsx b/packages/forms-collection/src/new-app/_form.tsx index 2bce21034..92f3a4c2f 100644 --- a/packages/forms-collection/src/new-app/_form.tsx +++ b/packages/forms-collection/src/new-app/_form.tsx @@ -72,7 +72,14 @@ export const AppForm = ({ } form.initialize(toFormValues(initialValues)); - }, [initialValuesKey, form, initialValues]); + // `form` is a new object every render (Mantine useForm returns a fresh literal), + // so it must not be a dep here — it would re-run every render and, since + // form.initialize() always calls clearErrors() (new {} object) internally, + // trigger an infinite update loop. initialValuesKey (a primitive string) + // already captures the only case this effect exists for: re-initializing + // when initialValues actually changes (e.g. navigating between edit pages). + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [initialValuesKey]); // Debounce the name value with 200ms delay const [debouncedName] = useDebouncedValue(form.values.name, 200);