fix: conserver le focus du champ de recherche après navigation

Le form ne remount plus lors de nos propres navigations (recherche,
filtres, clear) — le focus est préservé. Le remount ne se fait que
lors de navigations externes (back/forward du navigateur) pour syncer
les valeurs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-29 18:08:25 +02:00
parent 69de2ae237
commit caeb9f989f

View File

@@ -97,10 +97,12 @@ export function LiveSearchForm({ fields, basePath, debounceMs = 300 }: LiveSearc
if (timerRef.current) clearTimeout(timerRef.current); if (timerRef.current) clearTimeout(timerRef.current);
if (immediate) { if (immediate) {
saveFilters(); saveFilters();
isOwnNavRef.current = true;
startTransition(() => { router.replace(buildUrl() as any); }); startTransition(() => { router.replace(buildUrl() as any); });
} else { } else {
timerRef.current = setTimeout(() => { timerRef.current = setTimeout(() => {
saveFilters(); saveFilters();
isOwnNavRef.current = true;
startTransition(() => { router.replace(buildUrl() as any); }); startTransition(() => { router.replace(buildUrl() as any); });
}, debounceMs); }, debounceMs);
} }
@@ -120,18 +122,31 @@ export function LiveSearchForm({ fields, basePath, debounceMs = 300 }: LiveSearc
const textFields = fields.filter((f) => f.type === "text"); const textFields = fields.filter((f) => f.type === "text");
const selectFields = fields.filter((f) => f.type === "select"); const selectFields = fields.filter((f) => f.type === "select");
// Force remount when URL params change externally (back/forward, cookie redirect) // Track whether the current navigation was initiated by us (not back/forward)
// so that defaultValue stays in sync with the URL. const isOwnNavRef = useRef(false);
const formKey = searchParams.toString();
// Force remount only on external navigation (back/forward, cookie redirect)
// Our own navigations skip remount to preserve focus.
const prevParamsRef = useRef(searchParams.toString());
const formKey = useRef(0);
const currentParams = searchParams.toString();
if (currentParams !== prevParamsRef.current) {
if (!isOwnNavRef.current) {
formKey.current += 1; // External nav → remount
}
isOwnNavRef.current = false;
prevParamsRef.current = currentParams;
}
return ( return (
<form <form
key={formKey} key={formKey.current}
ref={formRef} ref={formRef}
onSubmit={(e) => { onSubmit={(e) => {
e.preventDefault(); e.preventDefault();
if (timerRef.current) clearTimeout(timerRef.current); if (timerRef.current) clearTimeout(timerRef.current);
saveFilters(); saveFilters();
isOwnNavRef.current = true;
startTransition(() => { router.replace(buildUrl() as any); }); startTransition(() => { router.replace(buildUrl() as any); });
}} }}
className="space-y-4" className="space-y-4"
@@ -191,6 +206,7 @@ export function LiveSearchForm({ fields, basePath, debounceMs = 300 }: LiveSearc
onClick={() => { onClick={() => {
formRef.current?.reset(); formRef.current?.reset();
try { deleteCookie(cookieName); } catch {} try { deleteCookie(cookieName); } catch {}
isOwnNavRef.current = true;
startTransition(() => { router.replace(basePath as any); }); startTransition(() => { router.replace(basePath as any); });
}} }}
className=" className="