URL State Management

NEVER use raw useSearchParams — always use the dedicated hooks from frontend/src/hooks/url-state/.

Available Hooks

HookPurposeExample
useTabState(validTabs, default)Tab switching with URL sync?tab=details
useFilterState(defaults)Multi-param filter state?status=active&search=solar
useModalState(param?)Deep-linkable modal/dialog?modal=create
useMultiSortState(columns, defaultSort)Multi-column sort with Shift+Click stacking?sort=name.asc,date.desc

All hooks are exported from frontend/src/hooks/url-state/index.ts.

Benefits

  • Shareable URLs — copy/paste a filtered view to a colleague
  • Browser navigation — back/forward buttons work with state changes
  • Refresh survival — state persists across page reloads
  • Bookmarkable — save specific filtered/sorted views

Usage Examples

// Tab management
const [activeTab, setActiveTab] = useTabState(['overview', 'details', 'files'], 'overview');
 
// Filter state with defaults
const [filters, setFilters] = useFilterState({
  status: 'all',
  search: '',
});

Multi-Sort

useMultiSortState supports stacking sort columns via Shift+Click:

const [sort, toggleSort] = useMultiSortState(
  ['name', 'date', 'status'],
  [{ column: 'date', direction: 'desc' }]
);

Single click replaces the sort. Shift+Click adds a secondary sort column.

Testing

Tests live in frontend/src/hooks/url-state/__tests__/ covering all four hooks.

See Also