perf(parcel-sync): use useDeferredValue for UAT search input

React's useDeferredValue lets the input update immediately while
deferring the expensive filter (3186 items) to a lower priority.
Removes the setTimeout debounce in favor of React's built-in
concurrent rendering scheduler. Input stays responsive.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
AI Assistant
2026-03-23 12:30:47 +02:00
parent 62777e9778
commit 2886703d0f
@@ -1,6 +1,6 @@
"use client";
import { useState, useEffect, useCallback, useMemo, useRef } from "react";
import { useState, useEffect, useCallback, useMemo, useRef, useDeferredValue } from "react";
import {
Search,
Download,
@@ -615,16 +615,17 @@ export function ParcelSyncModule() {
/* UAT autocomplete filter */
/* ════════════════════════════════════════════════════════════ */
// useDeferredValue lets React prioritize the input update over the filter
const deferredUatQuery = useDeferredValue(uatQuery);
useEffect(() => {
const raw = uatQuery.trim();
const raw = deferredUatQuery.trim();
if (raw.length < 2) {
setUatResults([]);
return;
}
const timer = setTimeout(() => {
const isDigit = /^\d+$/.test(raw);
const query = normalizeText(raw);
// Filter and sort: UAT name matches first, then county-only matches
const nameMatches: typeof uatData = [];
const countyOnlyMatches: typeof uatData = [];
@@ -640,12 +641,9 @@ export function ParcelSyncModule() {
}
}
// UAT name matches first (priority), then county-only matches
const results = [...nameMatches, ...countyOnlyMatches].slice(0, 12);
setUatResults(results);
}, 150);
return () => clearTimeout(timer);
}, [uatQuery, uatData]);
}, [deferredUatQuery, uatData]);
/* ════════════════════════════════════════════════════════════ */
/* Auto-connect: trigger on first UAT keystroke */