Skip to content

fix: preserve sessions date filter when closing session modal#4114

Open
Lokimorty wants to merge 1 commit intoumami-software:masterfrom
Lokimorty:persist-session-filter
Open

fix: preserve sessions date filter when closing session modal#4114
Lokimorty wants to merge 1 commit intoumami-software:masterfrom
Lokimorty:persist-session-filter

Conversation

@Lokimorty
Copy link
Copy Markdown
Contributor

Summary

When a user selects a custom Sessions page date filter such as Last 7 days, opens a session, and then closes the session modal, the page currently falls back to the default Last 24 hours filter.

Root Cause

useNavigation() was copying searchParams into local state and syncing them in an effect. That meant updateParams() could build the modal close URL from stale query state and drop the current date parameter.

Fix

Use the current useSearchParams() values directly when building URLs instead of mirroring them through local state.

This keeps the existing query string intact when the session modal is opened or closed, so the selected Sessions date filter persists as expected.

Changed Files

  • src/components/hooks/useNavigation.ts — remove the mirrored query state and build query, updateParams(), and renderUrl() from the live search params

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 27, 2026

@Lokimorty is attempting to deploy a commit to the Umami Software Team on Vercel.

A member of the Team first needs to authorize it.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 27, 2026

Greptile Summary

This PR fixes a bug where the Sessions page date filter (e.g. "Last 7 days") was silently dropped back to the default when a user closed the session detail modal. The root cause was a stale-state anti-pattern in useNavigation: searchParams was copied into React state on mount and re-synced via a useEffect, leaving a render gap in which updateParams/renderUrl could build the modal-close URL from an outdated snapshot of the query string.

Key changes:

  • Replaces useState + useEffect mirroring with a direct Object.fromEntries(searchParams.entries()) call in the render body, so queryParams is always the live value from Next.js's useSearchParams().
  • Removes useEffect and useState imports that are no longer needed.
  • Broadens the parameter value type from string | number to string | number | undefined, enabling callers to explicitly pass undefined to remove a specific query key (which buildPathgetQueryString already handled correctly by filtering out undefined values).

The fix is minimal, correct, and well-scoped. useSearchParams() in the Next.js App Router is reactive and returns a fresh read-only URLSearchParams instance on each render, so reading it directly is the idiomatic approach and removes the unnecessary indirection.

Confidence Score: 5/5

Safe to merge — the change is a well-targeted removal of a stale-state pattern with no new logic introduced.

The change is small, focused, and directly addresses the documented root cause. The new approach (reading useSearchParams() directly) is idiomatic for Next.js App Router and eliminates the one-render-gap race that caused the bug. buildPath already handles undefined values correctly, so the type-signature broadening is safe. No P0 or P1 issues were found.

No files require special attention.

Important Files Changed

Filename Overview
src/components/hooks/useNavigation.ts Removes stale-state pattern (useState + useEffect mirror of searchParams) in favour of reading searchParams directly each render; also broadens param value types to include undefined to allow explicit param removal.

Sequence Diagram

sequenceDiagram
    participant C as Component
    participant uN as useNavigation
    participant uSP as useSearchParams()
    participant bP as buildPath()

    Note over uN: Before (stale-state pattern)
    C->>uN: mount / render
    uN->>uSP: initial read → useState(Object.fromEntries(searchParams))
    Note over uN: queryParams state = snapshot at mount
    C->>uN: user changes date filter (searchParams updated)
    uN-->>uN: useEffect fires → setQueryParams(new snapshot)
    Note over uN: 1 render gap where queryParams is stale
    C->>uN: updateParams({view: 'session'})
    uN->>bP: buildPath(pathname, { ...staleQueryParams, view:'session' })
    Note over bP: date param may be missing

    Note over uN: After (live read)
    C->>uN: mount / render
    uN->>uSP: Object.fromEntries(searchParams.entries()) — always current
    C->>uN: updateParams({view: 'session'})
    uN->>bP: buildPath(pathname, { ...liveQueryParams, view:'session' })
    Note over bP: date param preserved correctly
Loading

Reviews (1): Last reviewed commit: "fix: preserve sessions date filter when ..." | Re-trigger Greptile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant