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:
@@ -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="
|
||||||
|
|||||||
Reference in New Issue
Block a user