Skip to content

fix(ui): list search input resets while typing (regression from #146 persistence) #170

Description

@pskillen

Problem

As a consequence of #146 (persist list table sort, columns, and filters in localStorage), controlled text fields — especially list name search inputs — can reset while the operator is still typing.

When the user enters or deletes text quickly, especially on a list page that triggers a large re-render (filtered DataTable, distance sort, etc.), the field value is briefly overwritten from persisted/URL state and the keystroke is lost.

Typical symptom: backspacing to clear or shorten a search string, but deleted characters immediately reappear.

Suspected root cause

List search is a fully controlled input bound to URL search params via useChannelListQuery and useListNameQuery:

  • nameFiltersearchParams.get('q')
  • setNameFiltersetSearchParams on every keystroke and debouncedMerge*ListPrefs (300 ms) to localStorage

On mount / location.search change, a hydration useEffect restores prefs from localStorage when the URL has no relevant params (hasEntityListUrlParams / hasChannelListUrlParams).

Race when clearing or rapidly editing search:

  1. Operator deletes the last character → q is removed from the URL.
  2. Hydration effect sees no URL params and reads stale localStorage (debounced write has not flushed yet).
  3. Effect calls setSearchParams with the old q value → text reappears.

Heavy list re-renders (channels table + filters) may widen the window where URL/state and the input are briefly out of sync during rapid entry.

Possible fix

Debounce the filter input at the UI boundary — keep a short-lived local draft value in the text field and only commit to URL / localStorage after input settles (few hundred ms). Optionally show a subtle pending/spinner state while debouncing.

Alternative / complementary:

  • Do not re-hydrate from localStorage while the operator is actively editing (track focus / dirty flag).
  • Flush debounced prefs synchronously before hydration can read stale storage.
  • Hydrate only on initial route visit, not on every location.search change when the change originated from the same hook.

Affected

  • src/hooks/useChannelListQuery.ts
  • src/hooks/useListNameQuery.ts
  • src/lib/listPrefs/storage.tsdebouncedMerge*ListPrefs (300 ms)
  • src/components/SectionNav/sections/ChannelsListSectionNav.tsx — search TextInput
  • Entity list routes / section nav using useListNameQuery (zones, contacts, talk groups, RX group lists)
  • src/components/ui/DataTable.tsx — toolbar search prop if wired the same way

Repro (manual)

  1. Open Channels (or Zones / Contacts) with a persisted name search from a prior visit (#146).
  2. Click the search field and rapidly backspace to clear the filter (or edit several characters quickly).
  3. Actual: deleted text snaps back; typing feels "fighting" the field.
  4. Expected: field reflects keystrokes until input settles; persisted prefs update after debounce without clobbering active edits.

Repeat on Channels with distance filter / large channel count to reproduce under heavy table updates.

Test plan

  • Unit: rapid setNameFilter / clear does not re-hydrate stale localStorage q over the in-progress value.
  • Unit or component: debounced commit updates URL + storage after idle period.
  • Manual: backspace-to-clear search on zones and channels — text stays cleared.
  • Manual: reload without URL params still restores last persisted search when not actively editing.
  • Regression: URL params still win on explicit navigation/bookmark (#146 contract).

Related

  • Regression from #146 — persist list table sort, columns and filters in localStorage
  • Follows #138 — standardised datatables (search in section nav / toolbar)

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingquality-of-lifefeature to improve the QOL of the person making a codeplug

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions