Skip to content

HistoryScreen: clear stale methodFilter when filtered method drops out of available set #1237

@cliffhall

Description

@cliffhall

Background

Surfaced in the Phase 5 audit PR review and deferred from that PR as a UX issue, not a spec-conformance gap.

HistoryScreen.tsx derives availableMethods from the live entries array and passes it to HistoryControls. The selected methodFilter is held in screen-local useState, independent of availableMethods.

When entries shrinks — most obviously after the user clicks Clear All — a previously-selected methodFilter can become absent from the new availableMethods set. The filter state is not reset, so the entry list shows zero results with no visible indication that the now-orphaned filter is the cause. The user has to manually clear the Select to recover.

Repro

  1. Generate some history (call any tool from the inspector).
  2. In the History screen, set the method filter to e.g. tools/call.
  3. Click Clear All.
  4. Trigger a request that produces history of a different method (e.g. resources/read).
  5. Notice the panel shows zero results because the stale tools/call filter still applies, even though tools/call is no longer in the dropdown.

Suggested fix

Three reasonable approaches; each has tradeoffs:

Option A — eager reset via effect. Add a useEffect in HistoryScreen that resets methodFilter to undefined when the current value falls out of availableMethods:

useEffect(() => {
  if (methodFilter && !availableMethods.includes(methodFilter)) {
    setMethodFilter(undefined);
  }
}, [availableMethods, methodFilter]);

Tradeoff: this is a state-update-in-effect, which the project's lint config disallows via react-hooks/set-state-in-effect (see InspectorView for the same constraint). Would need a refactor or lint suppression.

Option B — derive effective filter at render. Treat methodFilter as user intent that's preserved across transient empty states; compute an effectiveFilter at render that's undefined whenever the value isn't currently in availableMethods:

const effectiveFilter =
  methodFilter && availableMethods.includes(methodFilter) ? methodFilter : undefined;

Tradeoff: the HistoryControls Select still shows the stale value as selected (because it receives methodFilter, not effectiveFilter), so the displayed filter and the applied filter can diverge — confusing in its own way. Could pass effectiveFilter to the Select too, which would visually clear the dropdown but also discard the user's stored intent if entries grow back.

Option C — handler-driven reset. Reset methodFilter in the onClearAll handler (and any other handler that intentionally drops entries). Doesn't solve the general case (e.g. ephemeral entry expiration), but covers the obvious user-triggered path without effects or render-time logic.

Recommend C for the simplest correct fix, with B as a defensive backstop if other shrink paths emerge.

Out of scope

Metadata

Metadata

Assignees

Labels

v2Issues and PRs for v2

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions