From 73e8f51936b194f1c65fef6b138ee9c05a2e9867 Mon Sep 17 00:00:00 2001 From: jerick Date: Mon, 25 May 2026 17:46:54 +0000 Subject: [PATCH] Fix transaction pagination resetting to page 1 on Next click MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The search debounce useEffect had `push` in its deps. Since useRouter() returns a new instance each render, `push` was recreated on every navigation, re-triggering the effect which called push({ search }) after 400ms — always deleting the page param and snapping back to 1. Replace the useEffect debounce with a ref-based timer in the handler so the debounce only fires when the user actually types. Co-Authored-By: Claude Sonnet 4.6 --- .../transactions/TransactionFilters.tsx | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/components/transactions/TransactionFilters.tsx b/src/components/transactions/TransactionFilters.tsx index 3395468..5ffa9d9 100644 --- a/src/components/transactions/TransactionFilters.tsx +++ b/src/components/transactions/TransactionFilters.tsx @@ -35,11 +35,15 @@ export function TransactionFilters({ accounts }: { accounts: AccountOption[] }) [pathname, router], ) - // Debounce search → URL - useEffect(() => { - const t = setTimeout(() => push({ search }), 400) - return () => clearTimeout(t) - }, [search, push]) + const pushRef = useRef(push) + useEffect(() => { pushRef.current = push }, [push]) + const searchTimer = useRef | null>(null) + + function handleSearchChange(value: string) { + setSearch(value) + if (searchTimer.current) clearTimeout(searchTimer.current) + searchTimer.current = setTimeout(() => pushRef.current({ search: value }), 400) + } function reset() { setSearch('') @@ -107,7 +111,7 @@ export function TransactionFilters({ accounts }: { accounts: AccountOption[] }) className="h-8 text-sm" placeholder="Search descriptions…" value={search} - onChange={(e) => setSearch(e.target.value)} + onChange={(e) => handleSearchChange(e.target.value)} />