Skip to content

react-router migration batch 1: shared components, contexts and hooks#382

Closed
blaipr wants to merge 4 commits into
ctrliq:mainfrom
blaipr:feature/react-router-batch-1
Closed

react-router migration batch 1: shared components, contexts and hooks#382
blaipr wants to merge 4 commits into
ctrliq:mainfrom
blaipr:feature/react-router-batch-1

Conversation

@blaipr

@blaipr blaipr commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

📋 Merge instructions — all 13 open PRs, any order, zero conflicts

Every pair of open PRs has been verified conflict-free with git merge-tree (0 conflicts across all 78 pairs), and the union of all 13 was integration-tested green (Python suite 3477 passed, Jest 2873 passed, lint, build, licenses). Merge in any order you like. Two recommendations, not requirements:

The full queue:

  1. Merge PR Upgrade twisted, kubernetes, pyyaml, Cython and Django to latest allowed versions #374 - Upgrade twisted, kubernetes, pyyaml, Cython and Django to latest allowed versions
  2. Merge PR Upgrade django-oauth-toolkit 1.7.1 to 3.3.0 #376 - Upgrade django-oauth-toolkit 1.7.1 to 3.3.0
  3. Merge PR Upgrade styled-components from 5 to 6 #380 - Upgrade styled-components from 5 to 6
  4. Merge PR Begin react-router 5 → 6 migration via react-router-dom-v5-compat #381 - Begin react-router 5 → 6 migration via react-router-dom-v5-compat
  5. Merge PR react-router migration batch 1: shared components, contexts and hooks #382 - react-router migration batch 1: shared components, contexts and hooks ⬅️ this PR
  6. Merge PR react-router migration batch 2: screen directories (all except Inventory and Setting) #383 - react-router migration batch 2: screen directories (all except Inventory and Setting)
  7. Merge PR react-router migration batch 3: Inventory and Setting screens #384 - react-router migration batch 3: Inventory and Setting screens
  8. Merge PR Add React Testing Library migration infrastructure and first conversions #385 - Add React Testing Library migration infrastructure and first conversions
  9. Merge PR Remove EOL msrestazure, msrest and adal dependencies #386 - Remove EOL msrestazure, msrest and adal dependencies
  10. Merge PR Fix cross-test mock leak behind the flaky parallel test failures #388 - Fix cross-test mock leak behind the flaky parallel test failures
  11. Merge PR Build Activity Stream links for inventory source sync schedules #389 - Build Activity Stream links for inventory source sync schedules
  12. Merge PR Surface an error when the webhook credential type lookup returns nothing #390 - Surface an error when the webhook credential type lookup returns nothing
  13. Merge PR Modernize the frontend toolchain: Lingui 6, ESLint 9 and @dagrejs/dagre #391 - Modernize the frontend toolchain: Lingui 6, ESLint 9 and @dagrejs/dagre

SUMMARY

First batch of the incremental react-router 5 → 6 migration, building on the v5-compat bridge from #381. This migrates the shared layer every screen depends on (31 source files in src/components, src/contexts, src/hooks):

  • useHistory()useNavigate(); history.push(x)navigate(x); history.replace(...)navigate(..., { replace: true })
  • history.location reads → useLocation()
  • conditional <Redirect><Navigate> (ContentError, Session)
  • the seven withRouter(...Lookup) wrappers → hooks; the withRouter(AppContainer) wrapper was dead (component never read the injected props) and is simply dropped
  • contexts/Session's history.listen POP-detection is rewritten with useLocation/useNavigationType, skipping the initial render to preserve v5's fire-on-change-only semantics

Deliberately left on v5 (route-tree phase, migrates last): Switch/Route/match.path files (Schedules.js, Schedule.js, ScreenHeader.js) and prefix-match useRouteMatch({ path }) checks (contexts/Config.js, UserAndTeamAccessAdd.js) — v6's useMatch has different (full-match) semantics, so those need individual care.

Test changes: NavExpandableGroup/RoutedTabs tests move from raw MemoryRouter mounts to mountWithContexts (migrated components need the v6 context); the InstanceList RTL test's custom wrapper gains the same controlled v6 Router layer the helpers use — without it the suite error-looped on useNavigate until the jest worker ran out of memory; a dead useHistory mock is removed and one malformed relative initialEntries path gains its leading slash (v6 normalizes paths; v5 preserved the malformed value).

Stacked on #381 (contains its commit — the CompatRouter bridge is a hard prerequisite for components using compat APIs). Merge #381 first; this PR's diff reduces to its own commit once that lands. Remaining after this batch: ~200 screen files, splittable by screen directory using the same recipe.

ISSUE TYPE

  • New or Enhanced Feature

COMPONENT NAME

  • UI

ASCENDER VERSION

awx: 25.4.1.dev5+gcda0899.d20260610

ADDITIONAL INFORMATION

All UI gates run against this branch state:

npm --prefix awx/ui run lint     # clean
npm --prefix awx/ui run test     # 544 suites passed (1 skipped), 2869 tests passed (5 skipped)
npm --prefix awx/ui run build    # production build succeeds

The v6-context requirement is self-enforcing in tests: any component migrated without the bridge in its test wrapper fails loudly (useNavigate() may be used only in the context of a <Router>), which is how the InstanceList wrapper gap was caught.

blaipr added 2 commits June 11, 2026 10:26
Stage 2 of the React stack modernization. react-router-dom 6/7 removed
Switch, useHistory, useRouteMatch, Redirect and withRouter, which 243
files here still use, so the migration has to be incremental. This sets
up the official bridge and migrates the first screen:

- Add react-router-dom-v5-compat (ships router v6 alongside v5) and
  mount CompatRouter inside the app's HashRouter, so v5 and v6 routing
  contexts coexist and components can be migrated file by file.
- Wire the v6 context into testUtils/enzymeHelpers: the v5 Router keeps
  its history subscription and drives re-renders, while a fully
  controlled nested v6 Router (location from v5 context, navigator =
  the shared history) provides the v6 context without a second
  subscription - no act() warnings, and shallow rendering still works.
- Migrate screens/Login as the demonstration slice: Redirect becomes
  Navigate (from the compat package), and the withRouter wrapper is
  dropped (the component never used the injected props).
- Remove a test.only in Login.test.js that had silenced the other 14
  Login tests since the initial import, and fix the two assertions that
  had rotted while dark (the custom login screen has no LoginMainHeader;
  branding-fetch errors fall back to the default logo without a modal).
  The suite now runs 2869 tests, 14 more than before.

Migration recipe for follow-up PRs, per component:
  useHistory().push(x)  -> useNavigate(); navigate(x)
  useRouteMatch().params -> useParams()
  <Redirect to={x} />    -> <Navigate to={x} />
  withRouter(C)          -> hooks (or delete if props unused)
importing from 'react-router-dom-v5-compat'; the root Switch in App.js
migrates last, then react-router-dom flips to v6 and the compat package
is removed.
…at APIs

First batch of the incremental react-router 5 -> 6 migration started in
the v5-compat bridge PR. Migrates the shared layer every screen depends
on (31 files): useHistory becomes useNavigate, history.location reads
become useLocation(), conditional Redirect becomes Navigate, and the
seven withRouter(Lookup) wrappers plus the dead withRouter(AppContainer)
wrapper are replaced with hooks. history.replace(...) calls become
navigate(..., { replace: true }).

Deliberately left on v5 (route-tree phase, migrates last):
Switch/Route/match.path usage (components/Schedule/Schedules.js,
Schedule.js, ScreenHeader.js) and prefix-match useRouteMatch({ path })
checks (contexts/Config.js, UserAndTeamAccessAdd.js).

Session.js's history.listen(POP) logic is rewritten with
useLocation/useNavigationType, skipping the initial render to keep v5's
fire-on-change-only semantics.

Test updates: NavExpandableGroup and RoutedTabs tests move from raw
MemoryRouter mounts to mountWithContexts (migrated components need the
v6 context); the InstanceList RTL test's custom wrapper gains the same
controlled v6 Router layer the helpers use - without it the suite
error-looped on useNavigate and crashed its jest worker; a dead
useHistory mock is removed from AddResourceRole tests and a
malformed relative initialEntries path gains its leading slash (v6
normalizes paths, v5 preserved the malformed value).
navigate() from react-router-dom-v5-compat changes identity with the
location (unlike v5's stable history object), so including it in this
effect's deps refires the query-param-clearing navigation after
unrelated navigations. Same fix as the batch-3 redirect effects.
@blaipr

blaipr commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

Pushed a follow-up commit: navigate() from the compat package is not referentially stable (identity changes with location), so it's removed from the AddResourceRole effect deps with an explanatory eslint-disable — same pattern as documented in #384.

test_licenses requires every package.json dependency to have a matching
file in licenses/ui (caught by an integration run of the full Python
suite over all open PRs combined).

(cherry picked from commit c8103b1)
@blaipr

blaipr commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #392, which unifies the v5-compat bridge and all three migration batches into a single PR (one squashed commit, identical content, full gates green). Done as part of making the whole queue conflict-free and mergeable in any order.

@blaipr blaipr closed this Jun 11, 2026
@blaipr blaipr deleted the feature/react-router-batch-1 branch June 11, 2026 13:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant