Skip to content

CONSOLE-4990: Migrate from history object to React Router v6/v7 hooks#15956

Open
rhamilto wants to merge 1 commit intoopenshift:mainfrom
rhamilto:CONSOLE-4990
Open

CONSOLE-4990: Migrate from history object to React Router v6/v7 hooks#15956
rhamilto wants to merge 1 commit intoopenshift:mainfrom
rhamilto:CONSOLE-4990

Conversation

@rhamilto
Copy link
Member

@rhamilto rhamilto commented Jan 28, 2026

Summary

Migrates from direct history object usage to React Router v6/v7 compatible hook-based patterns as part of the React Router v7 upgrade effort.

Core Implementation

New useQueryParamsMutator() Hook

  • Provides query parameter mutation functions (setQueryArgument, setQueryArguments, setAllQueryArguments, removeQueryArgument, removeQueryArguments, setOrRemoveQueryArgument)
  • Uses useSearchParams() from react-router-dom-v5-compat
  • Stable function references via useRef pattern - prevents unnecessary re-renders and eliminates dependency array workarounds
  • Only triggers updates when values actually change (performance optimization)
  • Uses replace: true to avoid polluting browser history
  • Preserves location.hash and location.state on all mutations
  • Comprehensive unit tests in router-hooks.spec.tsx

Migration Scope

19 Files Migrated:

Easy conversions (added hook call, updated imports):

  • public/components/filter-toolbar.tsx
  • public/components/search.tsx
  • public/components/api-explorer.tsx
  • public/components/cluster-settings/cluster-settings.tsx
  • public/components/namespace-bar.tsx
  • public/components/useRowFilterFix.ts
  • public/components/useLabelSelectionFix.ts
  • public/components/useSearchFilters.ts
  • packages/topology/src/components/page/TopologyPage.tsx
  • packages/topology/src/components/page/TopologyView.tsx
  • packages/topology/src/filters/TopologyFilterBar.tsx
  • packages/console-shared/src/components/catalog/CatalogController.tsx
  • packages/operator-lifecycle-manager/src/components/subscription.tsx
  • packages/operator-lifecycle-manager/src/components/operator-hub/operator-channel-version-select.tsx
  • packages/console-app/src/components/nodes/NodeLogs.tsx

Complex refactors:

  • pod-logs.jsx - Functional wrapper pattern to inject hooks without class conversion
  • filter-utils.ts - Removed deprecated functions, moved logic to TopologyFilterBar
  • QuickSearchModalBody.tsx + 4 files - Replaced history.push() with useNavigate()

Bug Fixes

  • ✅ Fixed "Clear all filters" functionality in Search page and Topology filter bar by using removeQueryArguments() to atomically remove multiple params
  • ✅ Fixed getQueryArgument reference stability issue in TopologyPage useEffect by implementing searchParamsRef pattern (stable function references)

Code Cleanup

  • Removed deprecated query parameter mutation functions from router.ts
  • Removed unnecessary useRouterPush hook (use useNavigate() directly)
  • Removed unnecessary location.state from setSearchParams calls (React Router preserves state automatically with replace: true)
  • Removed eslint-disable workaround in TopologyPage (no longer needed with stable refs)

Test Improvements

  • Updated TopologyPage tests to mock useQueryParamsMutator directly instead of low-level router hooks (better abstraction, more maintainable)
  • All 19 router hook tests passing
  • All 9 TopologyPage tests passing

What Remains

The history object export is kept as it's still used by:

Related

Part of React Router v7 upgrade effort (CONSOLE-4990)

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jan 28, 2026
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Jan 28, 2026

@rhamilto: This pull request references CONSOLE-4990 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

Migrate from direct history object usage to React Router v6/v7 compatible hook-based patterns.

Progress: 19 of 20 files migrated (95% complete)

Changes

New Hooks

  • useQueryParamsMutator(): Returns 7 query parameter mutation functions

  • getQueryArgument, setQueryArgument, setQueryArguments, setAllQueryArguments

  • removeQueryArgument, removeQueryArguments, setOrRemoveQueryArgument

  • Uses useSearchParams() from react-router-dom-v5-compat

  • Preserves URL hash and location state

  • Optimized with change detection (only updates when values change)

  • useRouterPush(): Replacement for history.push() calls

  • Returns memoized navigate function

  • Compatible with React Router v6/v7

Files Migrated (19)

Custom Hooks (3):

  • useSearchFilters.ts
  • useRowFilterFix.ts
  • useLabelSelectionFix.ts

Components (16):

  • NodeLogs.tsx
  • filter-toolbar.tsx
  • namespace-bar.tsx
  • cluster-settings.tsx
  • TopologyFilterBar.tsx (+ removed deprecated functions from filter-utils.ts)
  • TopologyPage.tsx
  • TopologyView.tsx
  • search.tsx
  • api-explorer.tsx
  • CatalogController.tsx
  • QuickSearchModalBody.tsx (+ 4 related files)
  • subscription.tsx
  • operator-channel-version-select.tsx

Key Features

  • ✅ Comprehensive test suite (20/20 tests passing)
  • ✅ Zero TypeScript errors
  • ✅ All migrations preserve URL hash and location state
  • ✅ Consistent patterns across all migrations
  • ✅ Deprecated legacy functions marked with @deprecated for gradual migration

Testing

# TypeScript compilation
yarn tsc --noEmit  # ✅ Passing

# Unit tests
yarn test router-hooks.spec  # ✅ 20/20 passing

Remaining Work

  • pod-logs.jsx: Class → functional component conversion (final file)
  • Manual testing of key user flows
  • Remove deprecated functions from router.ts (after all migrations complete)

Related

  • Part of CONSOLE-4392: Upgrade to react-router v7
  • Story points: 8

🤖 Generated with Claude Code

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jan 28, 2026
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Jan 28, 2026

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@openshift-ci openshift-ci bot added component/core Related to console core functionality component/olm Related to OLM approved Indicates a PR has been approved by an approver from all required OWNERS files. component/shared Related to console-shared component/topology Related to topology labels Jan 28, 2026
@rhamilto rhamilto marked this pull request as ready for review January 28, 2026 22:07
@openshift-ci openshift-ci bot requested review from Leo6Leo and jhadvig January 28, 2026 22:07
rhamilto added a commit to rhamilto/console that referenced this pull request Jan 29, 2026
Replace direct history object usage with React Router v6/v7 compatible
hooks to prepare for react-router v7 upgrade.

## Key Changes

### New Hook API (public/components/utils/router.ts)

**useQueryParamsMutator()**
- Returns 7 query parameter mutation functions using useSearchParams()
- Preserves URL hash and location state during updates
- Only triggers updates when values actually change (optimization)
- Uses replace mode to avoid polluting browser history

**useRouterPush()**
- Replacement for direct history.push() calls
- Uses useNavigate() from react-router-dom-v5-compat

### Migration Pattern

Components now import and use hooks instead of utility functions:

**Before:**
```typescript
import { setQueryArgument } from '@console/internal/components/utils/router';

const MyComponent = () => {
  const onClick = () => setQueryArgument('key', 'value');
  return <button onClick={onClick}>Click</button>;
};
```

**After:**
```typescript
import { useQueryParamsMutator } from '@console/internal/components/utils/router';

const MyComponent = () => {
  const { setQueryArgument } = useQueryParamsMutator();
  const onClick = () => setQueryArgument('key', 'value');
  return <button onClick={onClick}>Click</button>;
};
```

## Files Migrated (19 of 20)

### Easy Conversions (14 files)
- public/components/useRowFilterFix.ts
- public/components/useLabelSelectionFix.ts
- public/components/useSearchFilters.ts
- public/components/filter-toolbar.tsx
- public/components/search.tsx
- public/components/api-explorer.tsx
- public/components/cluster-settings/cluster-settings.tsx
- public/components/namespace-bar.tsx
- packages/console-app/src/components/nodes/NodeLogs.tsx
- packages/console-shared/src/components/catalog/CatalogController.tsx
- packages/topology/src/components/page/TopologyPage.tsx
- packages/topology/src/components/page/TopologyView.tsx
- packages/operator-lifecycle-manager/src/components/subscription.tsx
- packages/operator-lifecycle-manager/src/components/operator-hub/operator-channel-version-select.tsx

### Complex Migrations (5 files)

**QuickSearch component tree** - Required prop drilling navigate/removeQueryArgument:
- packages/console-shared/src/components/quick-search/QuickSearchModalBody.tsx
- packages/console-shared/src/components/quick-search/QuickSearchContent.tsx
- packages/console-shared/src/components/quick-search/QuickSearchList.tsx
- packages/console-shared/src/components/quick-search/QuickSearchDetails.tsx
- packages/console-shared/src/components/quick-search/utils/quick-search-utils.tsx

**TopologyFilterBar** - Replaced utility functions with direct hook usage:
- packages/topology/src/filters/TopologyFilterBar.tsx
- packages/topology/src/filters/filter-utils.ts (removed deprecated functions)

## Testing

**Unit Tests:**
- Added comprehensive tests for new hooks (public/components/utils/__tests__/router-hooks.spec.tsx)
- All existing tests pass (20/20 ✓)

**Type Safety:**
- Zero TypeScript errors
- All TSDoc warnings fixed

**Code Quality:**
- ESLint pre-commit hooks pass
- Dependency arrays updated correctly

## Remaining Work

- 1 file remains: public/components/pod-logs.jsx (class → functional component conversion)
- Manual testing of key user flows
- Remove deprecated functions after all migrations complete

## Related

- Epic: CONSOLE-4392 (Upgrade to react-router v7)
- PR: openshift#15956

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
rhamilto added a commit to rhamilto/console that referenced this pull request Jan 29, 2026
Replace direct history object usage with React Router v6/v7 compatible
hooks to prepare for react-router v7 upgrade.

## Key Changes

### New Hook API (public/components/utils/router.ts)

**useQueryParamsMutator()**
- Returns 7 query parameter mutation functions using useSearchParams()
- Preserves URL hash and location state during updates
- Only triggers updates when values actually change (optimization)
- Uses replace mode to avoid polluting browser history

**useRouterPush()**
- Replacement for direct history.push() calls
- Uses useNavigate() from react-router-dom-v5-compat

### Migration Pattern

Components now import and use hooks instead of utility functions:

**Before:**
```typescript
import { setQueryArgument } from '@console/internal/components/utils/router';

const MyComponent = () => {
  const onClick = () => setQueryArgument('key', 'value');
  return <button onClick={onClick}>Click</button>;
};
```

**After:**
```typescript
import { useQueryParamsMutator } from '@console/internal/components/utils/router';

const MyComponent = () => {
  const { setQueryArgument } = useQueryParamsMutator();
  const onClick = () => setQueryArgument('key', 'value');
  return <button onClick={onClick}>Click</button>;
};
```

## Files Migrated (19 of 20)

### Easy Conversions (14 files)
- public/components/useRowFilterFix.ts
- public/components/useLabelSelectionFix.ts
- public/components/useSearchFilters.ts
- public/components/filter-toolbar.tsx
- public/components/search.tsx
- public/components/api-explorer.tsx
- public/components/cluster-settings/cluster-settings.tsx
- public/components/namespace-bar.tsx
- packages/console-app/src/components/nodes/NodeLogs.tsx
- packages/console-shared/src/components/catalog/CatalogController.tsx
- packages/topology/src/components/page/TopologyPage.tsx
- packages/topology/src/components/page/TopologyView.tsx
- packages/operator-lifecycle-manager/src/components/subscription.tsx
- packages/operator-lifecycle-manager/src/components/operator-hub/operator-channel-version-select.tsx

### Complex Migrations (5 files)

**QuickSearch component tree** - Required prop drilling navigate/removeQueryArgument:
- packages/console-shared/src/components/quick-search/QuickSearchModalBody.tsx
- packages/console-shared/src/components/quick-search/QuickSearchContent.tsx
- packages/console-shared/src/components/quick-search/QuickSearchList.tsx
- packages/console-shared/src/components/quick-search/QuickSearchDetails.tsx
- packages/console-shared/src/components/quick-search/utils/quick-search-utils.tsx

**TopologyFilterBar** - Replaced utility functions with direct hook usage:
- packages/topology/src/filters/TopologyFilterBar.tsx
- packages/topology/src/filters/filter-utils.ts (removed deprecated functions)

## Testing

**Unit Tests:**
- Added comprehensive tests for new hooks (public/components/utils/__tests__/router-hooks.spec.tsx)
- All existing tests pass (20/20 ✓)

**Type Safety:**
- Zero TypeScript errors
- All TSDoc warnings fixed

**Code Quality:**
- ESLint pre-commit hooks pass
- Dependency arrays updated correctly

## Remaining Work

- 1 file remains: public/components/pod-logs.jsx (class → functional component conversion)
- Manual testing of key user flows
- Remove deprecated functions after all migrations complete

## Related

- Epic: CONSOLE-4392 (Upgrade to react-router v7)
- PR: openshift#15956

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
rhamilto added a commit to rhamilto/console that referenced this pull request Jan 29, 2026
Replace direct history object usage with React Router v6/v7 compatible
hooks to prepare for react-router v7 upgrade.

## Key Changes

### New Hook API (public/components/utils/router.ts)

**useQueryParamsMutator()**
- Returns 7 query parameter mutation functions using useSearchParams()
- Preserves URL hash and location state during updates
- Only triggers updates when values actually change (optimization)
- Uses replace mode to avoid polluting browser history

**useRouterPush()**
- Replacement for direct history.push() calls
- Uses useNavigate() from react-router-dom-v5-compat

### Migration Pattern

Components now import and use hooks instead of utility functions:

**Before:**
```typescript
import { setQueryArgument } from '@console/internal/components/utils/router';

const MyComponent = () => {
  const onClick = () => setQueryArgument('key', 'value');
  return <button onClick={onClick}>Click</button>;
};
```

**After:**
```typescript
import { useQueryParamsMutator } from '@console/internal/components/utils/router';

const MyComponent = () => {
  const { setQueryArgument } = useQueryParamsMutator();
  const onClick = () => setQueryArgument('key', 'value');
  return <button onClick={onClick}>Click</button>;
};
```

## Files Migrated (19 of 20)

### Easy Conversions (14 files)
- public/components/useRowFilterFix.ts
- public/components/useLabelSelectionFix.ts
- public/components/useSearchFilters.ts
- public/components/filter-toolbar.tsx
- public/components/search.tsx
- public/components/api-explorer.tsx
- public/components/cluster-settings/cluster-settings.tsx
- public/components/namespace-bar.tsx
- packages/console-app/src/components/nodes/NodeLogs.tsx
- packages/console-shared/src/components/catalog/CatalogController.tsx
- packages/topology/src/components/page/TopologyPage.tsx
- packages/topology/src/components/page/TopologyView.tsx
- packages/operator-lifecycle-manager/src/components/subscription.tsx
- packages/operator-lifecycle-manager/src/components/operator-hub/operator-channel-version-select.tsx

### Complex Migrations (5 files)

**QuickSearch component tree** - Required prop drilling navigate/removeQueryArgument:
- packages/console-shared/src/components/quick-search/QuickSearchModalBody.tsx
- packages/console-shared/src/components/quick-search/QuickSearchContent.tsx
- packages/console-shared/src/components/quick-search/QuickSearchList.tsx
- packages/console-shared/src/components/quick-search/QuickSearchDetails.tsx
- packages/console-shared/src/components/quick-search/utils/quick-search-utils.tsx

**TopologyFilterBar** - Replaced utility functions with direct hook usage:
- packages/topology/src/filters/TopologyFilterBar.tsx
- packages/topology/src/filters/filter-utils.ts (removed deprecated functions)

## Testing

**Unit Tests:**
- Added comprehensive tests for new hooks (public/components/utils/__tests__/router-hooks.spec.tsx)
- All existing tests pass (20/20 ✓)

**Type Safety:**
- Zero TypeScript errors
- All TSDoc warnings fixed

**Code Quality:**
- ESLint pre-commit hooks pass
- Dependency arrays updated correctly

## Remaining Work

- 1 file remains: public/components/pod-logs.jsx (class → functional component conversion)
- Manual testing of key user flows
- Remove deprecated functions after all migrations complete

## Related

- Epic: CONSOLE-4392 (Upgrade to react-router v7)
- PR: openshift#15956

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
rhamilto added a commit to rhamilto/console that referenced this pull request Jan 29, 2026
Replace direct history object usage with React Router v6/v7 compatible
hooks to prepare for react-router v7 upgrade.

## Key Changes

### New Hook API (public/components/utils/router.ts)

**useQueryParamsMutator()**
- Returns 7 query parameter mutation functions using useSearchParams()
- Preserves URL hash and location state during updates
- Only triggers updates when values actually change (optimization)
- Uses replace mode to avoid polluting browser history

**useRouterPush()**
- Replacement for direct history.push() calls
- Uses useNavigate() from react-router-dom-v5-compat

### Migration Pattern

Components now import and use hooks instead of utility functions:

**Before:**
```typescript
import { setQueryArgument } from '@console/internal/components/utils/router';

const MyComponent = () => {
  const onClick = () => setQueryArgument('key', 'value');
  return <button onClick={onClick}>Click</button>;
};
```

**After:**
```typescript
import { useQueryParamsMutator } from '@console/internal/components/utils/router';

const MyComponent = () => {
  const { setQueryArgument } = useQueryParamsMutator();
  const onClick = () => setQueryArgument('key', 'value');
  return <button onClick={onClick}>Click</button>;
};
```

## Files Migrated (19 of 20)

### Easy Conversions (14 files)
- public/components/useRowFilterFix.ts
- public/components/useLabelSelectionFix.ts
- public/components/useSearchFilters.ts
- public/components/filter-toolbar.tsx
- public/components/search.tsx
- public/components/api-explorer.tsx
- public/components/cluster-settings/cluster-settings.tsx
- public/components/namespace-bar.tsx
- packages/console-app/src/components/nodes/NodeLogs.tsx
- packages/console-shared/src/components/catalog/CatalogController.tsx
- packages/topology/src/components/page/TopologyPage.tsx
- packages/topology/src/components/page/TopologyView.tsx
- packages/operator-lifecycle-manager/src/components/subscription.tsx
- packages/operator-lifecycle-manager/src/components/operator-hub/operator-channel-version-select.tsx

### Complex Migrations (5 files)

**QuickSearch component tree** - Required prop drilling navigate/removeQueryArgument:
- packages/console-shared/src/components/quick-search/QuickSearchModalBody.tsx
- packages/console-shared/src/components/quick-search/QuickSearchContent.tsx
- packages/console-shared/src/components/quick-search/QuickSearchList.tsx
- packages/console-shared/src/components/quick-search/QuickSearchDetails.tsx
- packages/console-shared/src/components/quick-search/utils/quick-search-utils.tsx

**TopologyFilterBar** - Replaced utility functions with direct hook usage:
- packages/topology/src/filters/TopologyFilterBar.tsx
- packages/topology/src/filters/filter-utils.ts (removed deprecated functions)

## Testing

**Unit Tests:**
- Added comprehensive tests for new hooks (public/components/utils/__tests__/router-hooks.spec.tsx)
- All existing tests pass (20/20 ✓)

**Type Safety:**
- Zero TypeScript errors
- All TSDoc warnings fixed

**Code Quality:**
- ESLint pre-commit hooks pass
- Dependency arrays updated correctly

## Remaining Work

- 1 file remains: public/components/pod-logs.jsx (class → functional component conversion)
- Manual testing of key user flows
- Remove deprecated functions after all migrations complete

## Related

- Epic: CONSOLE-4392 (Upgrade to react-router v7)
- PR: openshift#15956

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@rhamilto rhamilto force-pushed the CONSOLE-4990 branch 2 times, most recently from 329e981 to 2b47c8e Compare January 29, 2026 15:18
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Jan 29, 2026

@rhamilto: This pull request references CONSOLE-4990 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

Migrate from direct history object usage to React Router v6/v7 compatible hooks as preparation for the react-router v7 upgrade.

Replaces 78 usages across 20 files with hook-based patterns that are compatible with React Router v6/v7.

Changes

New Hook API

useQueryParamsMutator() - Returns query parameter mutation functions

  • Uses useSearchParams() from react-router-dom-v5-compat
  • Preserves URL hash and location state during updates
  • Only triggers updates when values actually change (performance optimization)
  • Uses replace mode to avoid polluting browser history
  • Returns: getQueryArgument, setQueryArgument, setQueryArguments, setAllQueryArguments, removeQueryArgument, removeQueryArguments, setOrRemoveQueryArgument

useRouterPush() - Replacement for history.push() calls

  • Uses useNavigate() from react-router-dom-v5-compat
  • Returns a memoized navigation function

Migration Pattern

// Before
import { setQueryArgument } from '@console/internal/components/utils/router';
const onClick = () => setQueryArgument('key', 'value');

// After
import { useQueryParamsMutator } from '@console/internal/components/utils/router';
const { setQueryArgument } = useQueryParamsMutator();
const onClick = () => setQueryArgument('key', 'value');

Files Migrated (20 total)

Functional Components (19 files):

  • public/components/useRowFilterFix.ts
  • public/components/useLabelSelectionFix.ts
  • public/components/useSearchFilters.ts
  • public/components/filter-toolbar.tsx
  • public/components/search.tsx
  • public/components/api-explorer.tsx
  • public/components/cluster-settings/cluster-settings.tsx
  • public/components/namespace-bar.tsx
  • packages/console-app/src/components/nodes/NodeLogs.tsx
  • packages/console-shared/src/components/catalog/CatalogController.tsx
  • packages/console-shared/src/components/quick-search/QuickSearchModalBody.tsx
  • packages/console-shared/src/components/quick-search/QuickSearchContent.tsx
  • packages/console-shared/src/components/quick-search/QuickSearchList.tsx
  • packages/console-shared/src/components/quick-search/QuickSearchDetails.tsx
  • packages/console-shared/src/components/quick-search/utils/quick-search-utils.tsx
  • packages/topology/src/components/page/TopologyPage.tsx
  • packages/topology/src/components/page/TopologyView.tsx
  • packages/topology/src/filters/TopologyFilterBar.tsx
  • packages/operator-lifecycle-manager/src/components/subscription.tsx
  • packages/operator-lifecycle-manager/src/components/operator-hub/operator-channel-version-select.tsx

Class Component with Wrapper (1 file):

  • public/components/pod-logs.jsx - Used functional wrapper pattern to inject hooks as props without converting to functional component

Utility Cleanup:

  • packages/topology/src/filters/filter-utils.ts - Removed deprecated utility functions; consumers now use hooks directly

Testing

Unit Tests:

  • Added comprehensive tests for new hooks in public/components/utils/__tests__/router-hooks.spec.tsx
  • Fixed TopologyPage.spec.tsx to mock router hooks required by components
  • All 472 test suites passing

Type Safety:

  • Zero TypeScript compilation errors
  • Added TSDoc documentation with proper escaping

Code Quality:

  • All ESLint checks passing
  • Dependency arrays properly updated

Backward Compatibility

Old utility functions remain in place with @deprecated JSDoc tags:

  • setQueryArgument(), setQueryArguments(), setAllQueryArguments()
  • removeQueryArgument(), removeQueryArguments()
  • setOrRemoveQueryArgument()

These will be removed in a future PR after confirming no external consumers.

Related

Testing Instructions

  1. Verify topology view switching works: /topology/ns/default?view=list/topology/ns/default?view=graph
  2. Test topology search/label filters update URL correctly
  3. Verify pod logs container dropdown updates ?container= parameter
  4. Test quick search modal (Ctrl+Space) updates ?catalogSearch= parameter
  5. Check browser back/forward buttons work correctly
  6. Verify URL hash fragments are preserved during query param updates

Co-Authored-By: Claude Sonnet 4.5 noreply@anthropic.com

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

rhamilto added a commit to rhamilto/console that referenced this pull request Jan 29, 2026
Replace direct history object usage with React Router v6/v7 compatible
hooks to prepare for react-router v7 upgrade.

## Key Changes

### New Hook API (public/components/utils/router.ts)

**useQueryParamsMutator()**
- Returns 7 query parameter mutation functions using useSearchParams()
- Preserves URL hash and location state during updates
- Only triggers updates when values actually change (optimization)
- Uses replace mode to avoid polluting browser history

**useRouterPush()**
- Replacement for direct history.push() calls
- Uses useNavigate() from react-router-dom-v5-compat

### Migration Pattern

Components now import and use hooks instead of utility functions:

**Before:**
```typescript
import { setQueryArgument } from '@console/internal/components/utils/router';

const MyComponent = () => {
  const onClick = () => setQueryArgument('key', 'value');
  return <button onClick={onClick}>Click</button>;
};
```

**After:**
```typescript
import { useQueryParamsMutator } from '@console/internal/components/utils/router';

const MyComponent = () => {
  const { setQueryArgument } = useQueryParamsMutator();
  const onClick = () => setQueryArgument('key', 'value');
  return <button onClick={onClick}>Click</button>;
};
```

## Files Migrated (19 of 20)

### Easy Conversions (14 files)
- public/components/useRowFilterFix.ts
- public/components/useLabelSelectionFix.ts
- public/components/useSearchFilters.ts
- public/components/filter-toolbar.tsx
- public/components/search.tsx
- public/components/api-explorer.tsx
- public/components/cluster-settings/cluster-settings.tsx
- public/components/namespace-bar.tsx
- packages/console-app/src/components/nodes/NodeLogs.tsx
- packages/console-shared/src/components/catalog/CatalogController.tsx
- packages/topology/src/components/page/TopologyPage.tsx
- packages/topology/src/components/page/TopologyView.tsx
- packages/operator-lifecycle-manager/src/components/subscription.tsx
- packages/operator-lifecycle-manager/src/components/operator-hub/operator-channel-version-select.tsx

### Complex Migrations (5 files)

**QuickSearch component tree** - Required prop drilling navigate/removeQueryArgument:
- packages/console-shared/src/components/quick-search/QuickSearchModalBody.tsx
- packages/console-shared/src/components/quick-search/QuickSearchContent.tsx
- packages/console-shared/src/components/quick-search/QuickSearchList.tsx
- packages/console-shared/src/components/quick-search/QuickSearchDetails.tsx
- packages/console-shared/src/components/quick-search/utils/quick-search-utils.tsx

**TopologyFilterBar** - Replaced utility functions with direct hook usage:
- packages/topology/src/filters/TopologyFilterBar.tsx
- packages/topology/src/filters/filter-utils.ts (removed deprecated functions)

## Testing

**Unit Tests:**
- Added comprehensive tests for new hooks (public/components/utils/__tests__/router-hooks.spec.tsx)
- All existing tests pass (20/20 ✓)

**Type Safety:**
- Zero TypeScript errors
- All TSDoc warnings fixed

**Code Quality:**
- ESLint pre-commit hooks pass
- Dependency arrays updated correctly

## Remaining Work

- 1 file remains: public/components/pod-logs.jsx (class → functional component conversion)
- Manual testing of key user flows
- Remove deprecated functions after all migrations complete

## Related

- Epic: CONSOLE-4392 (Upgrade to react-router v7)
- PR: openshift#15956

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Jan 29, 2026

@rhamilto: This pull request references CONSOLE-4990 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

Migrate from direct history object usage to React Router v6/v7 compatible hooks as preparation for the react-router v7 upgrade.

Replaces 78 usages across 20 files with hook-based patterns that are compatible with React Router v6/v7.

Changes

New Hook API

useQueryParamsMutator() - Returns query parameter mutation functions

  • Uses useSearchParams() from react-router-dom-v5-compat
  • Preserves URL hash and location state during updates
  • Only triggers updates when values actually change (performance optimization)
  • Uses replace mode to avoid polluting browser history
  • Returns: getQueryArgument, setQueryArgument, setQueryArguments, setAllQueryArguments, removeQueryArgument, removeQueryArguments, setOrRemoveQueryArgument

useRouterPush() - Replacement for history.push() calls

  • Uses useNavigate() from react-router-dom-v5-compat
  • Returns a memoized navigation function

Migration Pattern

// Before
import { setQueryArgument } from '@console/internal/components/utils/router';
const onClick = () => setQueryArgument('key', 'value');

// After
import { useQueryParamsMutator } from '@console/internal/components/utils/router';
const { setQueryArgument } = useQueryParamsMutator();
const onClick = () => setQueryArgument('key', 'value');

Files Migrated (20 total)

Functional Components (19 files):

  • public/components/useRowFilterFix.ts
  • public/components/useLabelSelectionFix.ts
  • public/components/useSearchFilters.ts
  • public/components/filter-toolbar.tsx
  • public/components/search.tsx
  • public/components/api-explorer.tsx
  • public/components/cluster-settings/cluster-settings.tsx
  • public/components/namespace-bar.tsx
  • packages/console-app/src/components/nodes/NodeLogs.tsx
  • packages/console-shared/src/components/catalog/CatalogController.tsx
  • packages/console-shared/src/components/quick-search/QuickSearchModalBody.tsx
  • packages/console-shared/src/components/quick-search/QuickSearchContent.tsx
  • packages/console-shared/src/components/quick-search/QuickSearchList.tsx
  • packages/console-shared/src/components/quick-search/QuickSearchDetails.tsx
  • packages/console-shared/src/components/quick-search/utils/quick-search-utils.tsx
  • packages/topology/src/components/page/TopologyPage.tsx
  • packages/topology/src/components/page/TopologyView.tsx
  • packages/topology/src/filters/TopologyFilterBar.tsx
  • packages/operator-lifecycle-manager/src/components/subscription.tsx
  • packages/operator-lifecycle-manager/src/components/operator-hub/operator-channel-version-select.tsx

Class Component with Wrapper (1 file):

  • public/components/pod-logs.jsx - Used functional wrapper pattern to inject hooks as props without converting to functional component

Utility Cleanup:

  • packages/topology/src/filters/filter-utils.ts - Removed deprecated utility functions; consumers now use hooks directly

Testing

Unit Tests:

  • Added comprehensive tests for new hooks in public/components/utils/__tests__/router-hooks.spec.tsx
  • Fixed TopologyPage.spec.tsx to mock router hooks required by components
  • All 472 test suites passing

Type Safety:

  • Zero TypeScript compilation errors
  • Added TSDoc documentation with proper escaping

Code Quality:

  • All ESLint checks passing
  • Dependency arrays properly updated

Backward Compatibility

Old utility functions remain in place with @deprecated JSDoc tags:

  • setQueryArgument(), setQueryArguments(), setAllQueryArguments()
  • removeQueryArgument(), removeQueryArguments()
  • setOrRemoveQueryArgument()

These will be removed in a future PR after confirming no external consumers.

Related

Testing Instructions

  1. Verify topology view switching works: /topology/ns/default?view=list/topology/ns/default?view=graph
  2. Test topology search/label filters update URL correctly
  3. Verify pod logs container dropdown updates ?container= parameter
  4. Test quick search modal (Ctrl+Space) updates ?catalogSearch= parameter
  5. Check browser back/forward buttons work correctly
  6. Verify URL hash fragments are preserved during query param updates

Co-Authored-By: Claude Sonnet 4.5 noreply@anthropic.com

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

rhamilto added a commit to rhamilto/console that referenced this pull request Jan 29, 2026
Replace direct history object usage with React Router v6/v7 compatible
hooks to prepare for react-router v7 upgrade.

## Key Changes

### New Hook API (public/components/utils/router.ts)

**useQueryParamsMutator()**
- Returns 7 query parameter mutation functions using useSearchParams()
- Preserves URL hash and location state during updates
- Only triggers updates when values actually change (optimization)
- Uses replace mode to avoid polluting browser history

**useRouterPush()**
- Replacement for direct history.push() calls
- Uses useNavigate() from react-router-dom-v5-compat

### Migration Pattern

Components now import and use hooks instead of utility functions:

**Before:**
```typescript
import { setQueryArgument } from '@console/internal/components/utils/router';

const MyComponent = () => {
  const onClick = () => setQueryArgument('key', 'value');
  return <button onClick={onClick}>Click</button>;
};
```

**After:**
```typescript
import { useQueryParamsMutator } from '@console/internal/components/utils/router';

const MyComponent = () => {
  const { setQueryArgument } = useQueryParamsMutator();
  const onClick = () => setQueryArgument('key', 'value');
  return <button onClick={onClick}>Click</button>;
};
```

## Files Migrated (19 of 20)

### Easy Conversions (14 files)
- public/components/useRowFilterFix.ts
- public/components/useLabelSelectionFix.ts
- public/components/useSearchFilters.ts
- public/components/filter-toolbar.tsx
- public/components/search.tsx
- public/components/api-explorer.tsx
- public/components/cluster-settings/cluster-settings.tsx
- public/components/namespace-bar.tsx
- packages/console-app/src/components/nodes/NodeLogs.tsx
- packages/console-shared/src/components/catalog/CatalogController.tsx
- packages/topology/src/components/page/TopologyPage.tsx
- packages/topology/src/components/page/TopologyView.tsx
- packages/operator-lifecycle-manager/src/components/subscription.tsx
- packages/operator-lifecycle-manager/src/components/operator-hub/operator-channel-version-select.tsx

### Complex Migrations (5 files)

**QuickSearch component tree** - Required prop drilling navigate/removeQueryArgument:
- packages/console-shared/src/components/quick-search/QuickSearchModalBody.tsx
- packages/console-shared/src/components/quick-search/QuickSearchContent.tsx
- packages/console-shared/src/components/quick-search/QuickSearchList.tsx
- packages/console-shared/src/components/quick-search/QuickSearchDetails.tsx
- packages/console-shared/src/components/quick-search/utils/quick-search-utils.tsx

**TopologyFilterBar** - Replaced utility functions with direct hook usage:
- packages/topology/src/filters/TopologyFilterBar.tsx
- packages/topology/src/filters/filter-utils.ts (removed deprecated functions)

## Testing

**Unit Tests:**
- Added comprehensive tests for new hooks (public/components/utils/__tests__/router-hooks.spec.tsx)
- All existing tests pass (20/20 ✓)

**Type Safety:**
- Zero TypeScript errors
- All TSDoc warnings fixed

**Code Quality:**
- ESLint pre-commit hooks pass
- Dependency arrays updated correctly

## Remaining Work

- 1 file remains: public/components/pod-logs.jsx (class → functional component conversion)
- Manual testing of key user flows
- Remove deprecated functions after all migrations complete

## Related

- Epic: CONSOLE-4392 (Upgrade to react-router v7)
- PR: openshift#15956

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Jan 29, 2026

@rhamilto: This pull request references CONSOLE-4990 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

Migrate from direct history object usage to React Router v6/v7 compatible hooks as preparation for the react-router v7 upgrade.

Replaces 78 usages across 20 files with hook-based patterns and removes deprecated utility functions that are no longer needed.

Changes

New Hook API

useQueryParamsMutator() - Returns query parameter mutation functions

  • Uses useSearchParams() from react-router-dom-v5-compat
  • Preserves URL hash and location state during updates
  • Only triggers updates when values actually change (performance optimization)
  • Uses replace mode to avoid polluting browser history
  • Returns: getQueryArgument, setQueryArgument, setQueryArguments, setAllQueryArguments, removeQueryArgument, removeQueryArguments, setOrRemoveQueryArgument

useRouterPush() - Replacement for history.push() calls

  • Uses useNavigate() from react-router-dom-v5-compat
  • Returns a memoized navigation function

Migration Pattern

// Before
import { setQueryArgument } from '@console/internal/components/utils/router';
const onClick = () => setQueryArgument('key', 'value');

// After
import { useQueryParamsMutator } from '@console/internal/components/utils/router';
const { setQueryArgument } = useQueryParamsMutator();
const onClick = () => setQueryArgument('key', 'value');

Files Migrated (20 total)

Functional Components (19 files):

  • public/components/useRowFilterFix.ts
  • public/components/useLabelSelectionFix.ts
  • public/components/useSearchFilters.ts
  • public/components/filter-toolbar.tsx
  • public/components/search.tsx
  • public/components/api-explorer.tsx
  • public/components/cluster-settings/cluster-settings.tsx
  • public/components/namespace-bar.tsx
  • packages/console-app/src/components/nodes/NodeLogs.tsx
  • packages/console-shared/src/components/catalog/CatalogController.tsx
  • packages/console-shared/src/components/quick-search/QuickSearchModalBody.tsx
  • packages/console-shared/src/components/quick-search/QuickSearchContent.tsx
  • packages/console-shared/src/components/quick-search/QuickSearchList.tsx
  • packages/console-shared/src/components/quick-search/QuickSearchDetails.tsx
  • packages/console-shared/src/components/quick-search/utils/quick-search-utils.tsx
  • packages/topology/src/components/page/TopologyPage.tsx
  • packages/topology/src/components/page/TopologyView.tsx
  • packages/topology/src/filters/TopologyFilterBar.tsx
  • packages/operator-lifecycle-manager/src/components/subscription.tsx
  • packages/operator-lifecycle-manager/src/components/operator-hub/operator-channel-version-select.tsx

Class Component with Wrapper (1 file):

  • public/components/pod-logs.jsx - Used functional wrapper pattern to inject hooks as props without converting to functional component

Utility Cleanup:

  • packages/topology/src/filters/filter-utils.ts - Removed deprecated utility functions; consumers now use hooks directly
  • public/components/utils/router.ts - Removed all deprecated query parameter mutation functions (setQueryArgument, setQueryArguments, setAllQueryArguments, removeQueryArgument, removeQueryArguments, setOrRemoveQueryArgument)

Testing

Unit Tests:

  • Added comprehensive tests for new hooks in public/components/utils/__tests__/router-hooks.spec.tsx
  • Fixed TopologyPage.spec.tsx to mock router hooks required by components
  • All 472 test suites passing

Type Safety:

  • Zero TypeScript compilation errors
  • Added TSDoc documentation with proper escaping

Code Quality:

  • All ESLint checks passing
  • Dependency arrays properly updated

Retained for Backward Compatibility

The following are still exported from router.ts for backward compatibility with React Router v5:

  • history object - Still used by the Router component and event listeners
  • getQueryArgument() utility - Read-only function, safe to keep

Related

Testing Instructions

  1. Verify topology view switching works: /topology/ns/default?view=list/topology/ns/default?view=graph
  2. Test topology search/label filters update URL correctly
  3. Verify pod logs container dropdown updates ?container= parameter
  4. Test quick search modal (Ctrl+Space) updates ?catalogSearch= parameter
  5. Check browser back/forward buttons work correctly
  6. Verify URL hash fragments are preserved during query param updates

Co-Authored-By: Claude Sonnet 4.5 noreply@anthropic.com

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

1 similar comment
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Jan 29, 2026

@rhamilto: This pull request references CONSOLE-4990 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

Migrate from direct history object usage to React Router v6/v7 compatible hooks as preparation for the react-router v7 upgrade.

Replaces 78 usages across 20 files with hook-based patterns and removes deprecated utility functions that are no longer needed.

Changes

New Hook API

useQueryParamsMutator() - Returns query parameter mutation functions

  • Uses useSearchParams() from react-router-dom-v5-compat
  • Preserves URL hash and location state during updates
  • Only triggers updates when values actually change (performance optimization)
  • Uses replace mode to avoid polluting browser history
  • Returns: getQueryArgument, setQueryArgument, setQueryArguments, setAllQueryArguments, removeQueryArgument, removeQueryArguments, setOrRemoveQueryArgument

useRouterPush() - Replacement for history.push() calls

  • Uses useNavigate() from react-router-dom-v5-compat
  • Returns a memoized navigation function

Migration Pattern

// Before
import { setQueryArgument } from '@console/internal/components/utils/router';
const onClick = () => setQueryArgument('key', 'value');

// After
import { useQueryParamsMutator } from '@console/internal/components/utils/router';
const { setQueryArgument } = useQueryParamsMutator();
const onClick = () => setQueryArgument('key', 'value');

Files Migrated (20 total)

Functional Components (19 files):

  • public/components/useRowFilterFix.ts
  • public/components/useLabelSelectionFix.ts
  • public/components/useSearchFilters.ts
  • public/components/filter-toolbar.tsx
  • public/components/search.tsx
  • public/components/api-explorer.tsx
  • public/components/cluster-settings/cluster-settings.tsx
  • public/components/namespace-bar.tsx
  • packages/console-app/src/components/nodes/NodeLogs.tsx
  • packages/console-shared/src/components/catalog/CatalogController.tsx
  • packages/console-shared/src/components/quick-search/QuickSearchModalBody.tsx
  • packages/console-shared/src/components/quick-search/QuickSearchContent.tsx
  • packages/console-shared/src/components/quick-search/QuickSearchList.tsx
  • packages/console-shared/src/components/quick-search/QuickSearchDetails.tsx
  • packages/console-shared/src/components/quick-search/utils/quick-search-utils.tsx
  • packages/topology/src/components/page/TopologyPage.tsx
  • packages/topology/src/components/page/TopologyView.tsx
  • packages/topology/src/filters/TopologyFilterBar.tsx
  • packages/operator-lifecycle-manager/src/components/subscription.tsx
  • packages/operator-lifecycle-manager/src/components/operator-hub/operator-channel-version-select.tsx

Class Component with Wrapper (1 file):

  • public/components/pod-logs.jsx - Used functional wrapper pattern to inject hooks as props without converting to functional component

Utility Cleanup:

  • packages/topology/src/filters/filter-utils.ts - Removed deprecated utility functions; consumers now use hooks directly
  • public/components/utils/router.ts - Removed all deprecated query parameter mutation functions (setQueryArgument, setQueryArguments, setAllQueryArguments, removeQueryArgument, removeQueryArguments, setOrRemoveQueryArgument)

Testing

Unit Tests:

  • Added comprehensive tests for new hooks in public/components/utils/__tests__/router-hooks.spec.tsx
  • Fixed TopologyPage.spec.tsx to mock router hooks required by components
  • All 472 test suites passing

Type Safety:

  • Zero TypeScript compilation errors
  • Added TSDoc documentation with proper escaping

Code Quality:

  • All ESLint checks passing
  • Dependency arrays properly updated

Retained for Backward Compatibility

The following are still exported from router.ts for backward compatibility with React Router v5:

  • history object - Still used by the Router component and event listeners
  • getQueryArgument() utility - Read-only function, safe to keep

Related

Testing Instructions

  1. Verify topology view switching works: /topology/ns/default?view=list/topology/ns/default?view=graph
  2. Test topology search/label filters update URL correctly
  3. Verify pod logs container dropdown updates ?container= parameter
  4. Test quick search modal (Ctrl+Space) updates ?catalogSearch= parameter
  5. Check browser back/forward buttons work correctly
  6. Verify URL hash fragments are preserved during query param updates

Co-Authored-By: Claude Sonnet 4.5 noreply@anthropic.com

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

rhamilto added a commit to rhamilto/console that referenced this pull request Jan 29, 2026
Replace direct history object usage with React Router v6/v7 compatible
hooks to prepare for react-router v7 upgrade.

## Key Changes

### New Hook API (public/components/utils/router.ts)

**useQueryParamsMutator()**
- Returns 7 query parameter mutation functions using useSearchParams()
- Preserves URL hash and location state during updates
- Only triggers updates when values actually change (optimization)
- Uses replace mode to avoid polluting browser history

**useRouterPush()**
- Replacement for direct history.push() calls
- Uses useNavigate() from react-router-dom-v5-compat

### Migration Pattern

Components now import and use hooks instead of utility functions:

**Before:**
```typescript
import { setQueryArgument } from '@console/internal/components/utils/router';

const MyComponent = () => {
  const onClick = () => setQueryArgument('key', 'value');
  return <button onClick={onClick}>Click</button>;
};
```

**After:**
```typescript
import { useQueryParamsMutator } from '@console/internal/components/utils/router';

const MyComponent = () => {
  const { setQueryArgument } = useQueryParamsMutator();
  const onClick = () => setQueryArgument('key', 'value');
  return <button onClick={onClick}>Click</button>;
};
```

## Files Migrated (19 of 20)

### Easy Conversions (14 files)
- public/components/useRowFilterFix.ts
- public/components/useLabelSelectionFix.ts
- public/components/useSearchFilters.ts
- public/components/filter-toolbar.tsx
- public/components/search.tsx
- public/components/api-explorer.tsx
- public/components/cluster-settings/cluster-settings.tsx
- public/components/namespace-bar.tsx
- packages/console-app/src/components/nodes/NodeLogs.tsx
- packages/console-shared/src/components/catalog/CatalogController.tsx
- packages/topology/src/components/page/TopologyPage.tsx
- packages/topology/src/components/page/TopologyView.tsx
- packages/operator-lifecycle-manager/src/components/subscription.tsx
- packages/operator-lifecycle-manager/src/components/operator-hub/operator-channel-version-select.tsx

### Complex Migrations (5 files)

**QuickSearch component tree** - Required prop drilling navigate/removeQueryArgument:
- packages/console-shared/src/components/quick-search/QuickSearchModalBody.tsx
- packages/console-shared/src/components/quick-search/QuickSearchContent.tsx
- packages/console-shared/src/components/quick-search/QuickSearchList.tsx
- packages/console-shared/src/components/quick-search/QuickSearchDetails.tsx
- packages/console-shared/src/components/quick-search/utils/quick-search-utils.tsx

**TopologyFilterBar** - Replaced utility functions with direct hook usage:
- packages/topology/src/filters/TopologyFilterBar.tsx
- packages/topology/src/filters/filter-utils.ts (removed deprecated functions)

## Testing

**Unit Tests:**
- Added comprehensive tests for new hooks (public/components/utils/__tests__/router-hooks.spec.tsx)
- All existing tests pass (20/20 ✓)

**Type Safety:**
- Zero TypeScript errors
- All TSDoc warnings fixed

**Code Quality:**
- ESLint pre-commit hooks pass
- Dependency arrays updated correctly

## Remaining Work

- 1 file remains: public/components/pod-logs.jsx (class → functional component conversion)
- Manual testing of key user flows
- Remove deprecated functions after all migrations complete

## Related

- Epic: CONSOLE-4392 (Upgrade to react-router v7)
- PR: openshift#15956

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@openshift-ci-robot openshift-ci-robot removed the verified Signifies that the PR passed pre-merge verification criteria label Feb 4, 2026
@rhamilto
Copy link
Member Author

rhamilto commented Feb 4, 2026

/verified by @yapei

@openshift-ci-robot openshift-ci-robot added the verified Signifies that the PR passed pre-merge verification criteria label Feb 4, 2026
@openshift-ci-robot
Copy link
Contributor

@rhamilto: This PR has been marked as verified by @yapei.

Details

In response to this:

/verified by @yapei

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci-robot openshift-ci-robot removed the verified Signifies that the PR passed pre-merge verification criteria label Feb 4, 2026
@rhamilto rhamilto force-pushed the CONSOLE-4990 branch 2 times, most recently from 9a8dd02 to b5e3987 Compare February 4, 2026 19:21
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Feb 4, 2026

@rhamilto: This pull request references CONSOLE-4990 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

Migrates from direct history object usage to React Router v6/v7 compatible hook-based patterns as part of the React Router v7 upgrade effort.

Core Implementation

New useQueryParamsMutator() Hook

  • Provides query parameter mutation functions (setQueryArgument, setQueryArguments, setAllQueryArguments, removeQueryArgument, removeQueryArguments, setOrRemoveQueryArgument)
  • Uses useSearchParams() from react-router-dom-v5-compat
  • Stable function references via useRef pattern - prevents unnecessary re-renders and eliminates dependency array workarounds
  • Only triggers updates when values actually change (performance optimization)
  • Uses replace: true to avoid polluting browser history
  • Preserves location.hash and location.state on all mutations
  • Comprehensive unit tests in router-hooks.spec.tsx

Migration Scope

19 Files Migrated:

Easy conversions (added hook call, updated imports):

  • public/components/filter-toolbar.tsx
  • public/components/search.tsx
  • public/components/api-explorer.tsx
  • public/components/cluster-settings/cluster-settings.tsx
  • public/components/namespace-bar.tsx
  • public/components/useRowFilterFix.ts
  • public/components/useLabelSelectionFix.ts
  • public/components/useSearchFilters.ts
  • packages/topology/src/components/page/TopologyPage.tsx
  • packages/topology/src/components/page/TopologyView.tsx
  • packages/topology/src/filters/TopologyFilterBar.tsx
  • packages/console-shared/src/components/catalog/CatalogController.tsx
  • packages/operator-lifecycle-manager/src/components/subscription.tsx
  • packages/operator-lifecycle-manager/src/components/operator-hub/operator-channel-version-select.tsx
  • packages/console-app/src/components/nodes/NodeLogs.tsx

Complex refactors:

  • pod-logs.jsx - Functional wrapper pattern to inject hooks without class conversion
  • filter-utils.ts - Removed deprecated functions, moved logic to TopologyFilterBar
  • QuickSearchModalBody.tsx + 4 files - Replaced history.push() with useNavigate()

Bug Fixes

  • ✅ Fixed "Clear all filters" functionality in Search page and Topology filter bar by using removeQueryArguments() to atomically remove multiple params
  • ✅ Fixed getQueryArgument reference stability issue in TopologyPage useEffect by implementing searchParamsRef pattern (stable function references)

Code Cleanup

  • Removed deprecated query parameter mutation functions from router.ts
  • Removed unnecessary useRouterPush hook (use useNavigate() directly)
  • Removed unnecessary location.state from setSearchParams calls (React Router preserves state automatically with replace: true)
  • Removed eslint-disable workaround in TopologyPage (no longer needed with stable refs)

Test Improvements

  • Updated TopologyPage tests to mock useQueryParamsMutator directly instead of low-level router hooks (better abstraction, more maintainable)
  • All 19 router hook tests passing
  • All 9 TopologyPage tests passing

What Remains

The history object export is kept as it's still used by:

  • Router component initialization in app.tsx
  • Monkey-patching for base path handling
  • 20+ other files (separate migration tracked in CONSOLE-3147)

Related

Part of React Router v7 upgrade effort (CONSOLE-4990)

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

1 similar comment
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Feb 4, 2026

@rhamilto: This pull request references CONSOLE-4990 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

Migrates from direct history object usage to React Router v6/v7 compatible hook-based patterns as part of the React Router v7 upgrade effort.

Core Implementation

New useQueryParamsMutator() Hook

  • Provides query parameter mutation functions (setQueryArgument, setQueryArguments, setAllQueryArguments, removeQueryArgument, removeQueryArguments, setOrRemoveQueryArgument)
  • Uses useSearchParams() from react-router-dom-v5-compat
  • Stable function references via useRef pattern - prevents unnecessary re-renders and eliminates dependency array workarounds
  • Only triggers updates when values actually change (performance optimization)
  • Uses replace: true to avoid polluting browser history
  • Preserves location.hash and location.state on all mutations
  • Comprehensive unit tests in router-hooks.spec.tsx

Migration Scope

19 Files Migrated:

Easy conversions (added hook call, updated imports):

  • public/components/filter-toolbar.tsx
  • public/components/search.tsx
  • public/components/api-explorer.tsx
  • public/components/cluster-settings/cluster-settings.tsx
  • public/components/namespace-bar.tsx
  • public/components/useRowFilterFix.ts
  • public/components/useLabelSelectionFix.ts
  • public/components/useSearchFilters.ts
  • packages/topology/src/components/page/TopologyPage.tsx
  • packages/topology/src/components/page/TopologyView.tsx
  • packages/topology/src/filters/TopologyFilterBar.tsx
  • packages/console-shared/src/components/catalog/CatalogController.tsx
  • packages/operator-lifecycle-manager/src/components/subscription.tsx
  • packages/operator-lifecycle-manager/src/components/operator-hub/operator-channel-version-select.tsx
  • packages/console-app/src/components/nodes/NodeLogs.tsx

Complex refactors:

  • pod-logs.jsx - Functional wrapper pattern to inject hooks without class conversion
  • filter-utils.ts - Removed deprecated functions, moved logic to TopologyFilterBar
  • QuickSearchModalBody.tsx + 4 files - Replaced history.push() with useNavigate()

Bug Fixes

  • ✅ Fixed "Clear all filters" functionality in Search page and Topology filter bar by using removeQueryArguments() to atomically remove multiple params
  • ✅ Fixed getQueryArgument reference stability issue in TopologyPage useEffect by implementing searchParamsRef pattern (stable function references)

Code Cleanup

  • Removed deprecated query parameter mutation functions from router.ts
  • Removed unnecessary useRouterPush hook (use useNavigate() directly)
  • Removed unnecessary location.state from setSearchParams calls (React Router preserves state automatically with replace: true)
  • Removed eslint-disable workaround in TopologyPage (no longer needed with stable refs)

Test Improvements

  • Updated TopologyPage tests to mock useQueryParamsMutator directly instead of low-level router hooks (better abstraction, more maintainable)
  • All 19 router hook tests passing
  • All 9 TopologyPage tests passing

What Remains

The history object export is kept as it's still used by:

  • Router component initialization in app.tsx
  • Monkey-patching for base path handling
  • 20+ other files (separate migration tracked in CONSOLE-3147)

Related

Part of React Router v7 upgrade effort (CONSOLE-4990)

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@rhamilto
Copy link
Member Author

rhamilto commented Feb 4, 2026

@yapei, I had to push some changes and found the following bug

Fixed "Clear all filters" functionality in Search page and Topology filter bar by using removeQueryArguments() to atomically remove multiple params

Mind re-verifying?

@rhamilto
Copy link
Member Author

rhamilto commented Feb 4, 2026

Latest Updates

Addressed review feedback and fixed additional bugs:

1. Fixed getQueryArgument Reference Stability (PR Review Feedback)

Issue: getQueryArgument's reference was changing whenever searchParams changed, requiring workarounds like the one in TopologyPage.

Solution: Implemented searchParamsRef pattern for stable function references:

  • Added searchParamsRef to store current searchParams without triggering callback recreations
  • Updated all callbacks to use searchParamsRef.current instead of searchParams from closure
  • Removed searchParams from all dependency arrays (only navigate remains)
  • All returned functions now have stable references that don't change when query params change

Benefits:

  • No more eslint-disable workarounds needed
  • Proper dependency arrays without infinite loops
  • Better performance (fewer callback recreations)
  • Cleaner, more maintainable code

Changes:

  • public/components/utils/router.ts - Implemented searchParamsRef pattern
  • packages/topology/src/components/page/TopologyPage.tsx - Removed workaround, added getQueryArgument to deps array

2. Fixed "Clear All Filters" Bug

Issue: Clicking "Clear all filters" wasn't removing query parameters from the URL.

Root Cause: Calling individual removeQueryArgument() multiple times in sequence doesn't work properly with the ref-based implementation - the updates need to be atomic.

Solution: Use removeQueryArguments() (plural) to remove all params in a single navigation update.

Changes:

  • public/components/search.tsx - Changed clearAll() to use removeQueryArguments('kind', 'name', 'q')
  • packages/topology/src/filters/TopologyFilterBar.tsx - Changed clearAll() to use removeQueryArguments(TOPOLOGY_SEARCH_FILTER_KEY, TOPOLOGY_LABELS_FILTER_KEY)

Testing

✅ All tests passing:

  • router-hooks.spec.tsx - 19/19 tests passed
  • TopologyPage.spec.tsx - 9/9 tests passed

@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Feb 4, 2026

@rhamilto: This pull request references CONSOLE-4990 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

Migrates from direct history object usage to React Router v6/v7 compatible hook-based patterns as part of the React Router v7 upgrade effort.

Core Implementation

New useQueryParamsMutator() Hook

  • Provides query parameter mutation functions (setQueryArgument, setQueryArguments, setAllQueryArguments, removeQueryArgument, removeQueryArguments, setOrRemoveQueryArgument)
  • Uses useSearchParams() from react-router-dom-v5-compat
  • Stable function references via useRef pattern - prevents unnecessary re-renders and eliminates dependency array workarounds
  • Only triggers updates when values actually change (performance optimization)
  • Uses replace: true to avoid polluting browser history
  • Preserves location.hash and location.state on all mutations
  • Comprehensive unit tests in router-hooks.spec.tsx

Migration Scope

19 Files Migrated:

Easy conversions (added hook call, updated imports):

  • public/components/filter-toolbar.tsx
  • public/components/search.tsx
  • public/components/api-explorer.tsx
  • public/components/cluster-settings/cluster-settings.tsx
  • public/components/namespace-bar.tsx
  • public/components/useRowFilterFix.ts
  • public/components/useLabelSelectionFix.ts
  • public/components/useSearchFilters.ts
  • packages/topology/src/components/page/TopologyPage.tsx
  • packages/topology/src/components/page/TopologyView.tsx
  • packages/topology/src/filters/TopologyFilterBar.tsx
  • packages/console-shared/src/components/catalog/CatalogController.tsx
  • packages/operator-lifecycle-manager/src/components/subscription.tsx
  • packages/operator-lifecycle-manager/src/components/operator-hub/operator-channel-version-select.tsx
  • packages/console-app/src/components/nodes/NodeLogs.tsx

Complex refactors:

  • pod-logs.jsx - Functional wrapper pattern to inject hooks without class conversion
  • filter-utils.ts - Removed deprecated functions, moved logic to TopologyFilterBar
  • QuickSearchModalBody.tsx + 4 files - Replaced history.push() with useNavigate()

Bug Fixes

  • ✅ Fixed "Clear all filters" functionality in Search page and Topology filter bar by using removeQueryArguments() to atomically remove multiple params
  • ✅ Fixed getQueryArgument reference stability issue in TopologyPage useEffect by implementing searchParamsRef pattern (stable function references)

Code Cleanup

  • Removed deprecated query parameter mutation functions from router.ts
  • Removed unnecessary useRouterPush hook (use useNavigate() directly)
  • Removed unnecessary location.state from setSearchParams calls (React Router preserves state automatically with replace: true)
  • Removed eslint-disable workaround in TopologyPage (no longer needed with stable refs)

Test Improvements

  • Updated TopologyPage tests to mock useQueryParamsMutator directly instead of low-level router hooks (better abstraction, more maintainable)
  • All 19 router hook tests passing
  • All 9 TopologyPage tests passing

What Remains

The history object export is kept as it's still used by:

Related

Part of React Router v7 upgrade effort (CONSOLE-4990)

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@vojtechszocs
Copy link
Contributor

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Feb 4, 2026
@yapei
Copy link
Contributor

yapei commented Feb 5, 2026

it looks like pod logs can not be successfully loaded, others are working well
Screenshot 2026-02-05 at 11 53 17 AM

@rhamilto
Copy link
Member Author

rhamilto commented Feb 5, 2026

it looks like pod logs can not be successfully loaded, others are working well Screenshot 2026-02-05 at 11 53 17 AM

That is very strange. It seems to be working fine for me. Can you try again?

Screen.Recording.2026-02-05.at.8.07.02.AM.mov

@rhamilto
Copy link
Member Author

rhamilto commented Feb 5, 2026

/retest

Migrates from direct history object usage to React Router v6/v7 compatible
hook-based patterns as part of the React Router v7 upgrade effort.

- Created useQueryParamsMutator() hook providing query parameter mutation
  functions (setQueryArgument, setQueryArguments, setAllQueryArguments,
  removeQueryArgument, removeQueryArguments, setOrRemoveQueryArgument)
- Uses useSearchParams() from react-router-dom-v5-compat
- Stable function references via useRef pattern - prevents unnecessary re-renders
  and eliminates dependency array workarounds
- Only triggers updates when values actually change (performance optimization)
- Uses replace: true to avoid polluting browser history
- Preserves location.hash and location.state on all mutations
- Added comprehensive unit tests in router-hooks.spec.tsx

Easy conversions - Added hook call, updated imports:
- public/components/filter-toolbar.tsx
- public/components/search.tsx
- public/components/api-explorer.tsx
- public/components/cluster-settings/cluster-settings.tsx
- public/components/namespace-bar.tsx
- public/components/useRowFilterFix.ts
- public/components/useLabelSelectionFix.ts
- public/components/useSearchFilters.ts
- packages/topology/src/components/page/TopologyPage.tsx
- packages/topology/src/components/page/TopologyView.tsx
- packages/topology/src/filters/TopologyFilterBar.tsx
- packages/console-shared/src/components/catalog/CatalogController.tsx
- packages/operator-lifecycle-manager/src/components/subscription.tsx
- packages/operator-lifecycle-manager/src/components/operator-hub/operator-channel-version-select.tsx
- packages/console-app/src/components/nodes/NodeLogs.tsx

Complex refactors:
- pod-logs.jsx - Functional wrapper pattern to inject hooks without class conversion
- filter-utils.ts - Removed deprecated functions, moved logic to TopologyFilterBar
- QuickSearchModalBody.tsx + 4 files - Replaced history.push() with useNavigate()

- Fixed "Clear all filters" functionality in Search page and Topology filter bar
  by using removeQueryArguments() to atomically remove multiple params
- Fixed getQueryArgument reference stability issue in TopologyPage useEffect
  by implementing searchParamsRef pattern (addresses PR review feedback)

- Removed deprecated query parameter mutation functions from router.ts
- Removed unnecessary useRouterPush hook (use useNavigate() directly)
- Removed unnecessary location.state from setSearchParams calls (React Router
  preserves state automatically with replace: true)
- Removed eslint-disable workaround in TopologyPage (no longer needed)

- Updated TopologyPage tests to mock useQueryParamsMutator directly instead of
  low-level router hooks (better abstraction, more maintainable)

The history object export is kept as it's still used by:
- Router component initialization in app.tsx
- Monkey-patching for base path handling
- 20+ other files (separate migration)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@openshift-ci openshift-ci bot removed the lgtm Indicates that a PR is ready to be merged. label Feb 5, 2026
projectDropdown.shouldContain(installedNamespace);
operator.filterByName(operatorName);
listPage.rows.countShouldBe(1);
// TODO: figure out why this arbitrary wait is needed
Copy link
Member Author

@rhamilto rhamilto Feb 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a workaround we are using in a number of places within Cypress tests. It's far from ideal, but a proper fix feels like it's out of scope of this PR. To my knowledge, there is nothing specific within the PR that would be creating the need for this.

@rhamilto
Copy link
Member Author

rhamilto commented Feb 6, 2026

/retest

Copy link
Member

@logonoff logonoff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

Copy link
Member

@jhadvig jhadvig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Feb 6, 2026
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 6, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: jhadvig, logonoff, rhamilto, vojtechszocs

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 6, 2026

@rhamilto: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

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

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. component/core Related to console core functionality component/dev-console Related to dev-console component/helm Related to helm-plugin component/knative Related to knative-plugin component/metal3 Related to metal3-plugin component/olm Related to OLM component/shared Related to console-shared component/topology Related to topology docs-approved Signifies that Docs has signed off on this PR jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged. px-approved Signifies that Product Support has signed off on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants