Skip to content

Move to React 18 and react-router 7, and replace react-refetch - #465

Open
stephaniehobson wants to merge 9 commits into
depsfrom
react-18-upgrade
Open

stephaniehobson wants to merge 9 commits into
depsfrom
react-18-upgrade

Conversation

@stephaniehobson

Copy link
Copy Markdown
Collaborator

One-line summary

Move to React 18 and react-router 7, and replace the four packages that capped React (react-refetch, react-metrics-graphics, react-helmet, react-ga). React 19 is deferred because it makes charts appear later.

Significant changes and points to review

  • Replace react-refetch with src/lib/withFetch.jsx. It keeps the same dataFetch prop and behaviour:
    • it refetches when the URL changes, going back to pending first;
    • a non-2xx response rejects, with the message from the JSON body;
    • it ignores a response that arrives after a newer request started.
  • Replace react-metrics-graphics with views/MetricsGraphics.jsx, which calls MG.data_graphic directly.
  • Move react-router to 7 (through 6), importing from react-router. Main.jsx and both decorators now use useLocation().
    • The lazy route components are still created on each navigation. React remembers a failed chunk load for good, and this lets a route retry.
    • withTracker sends its page view from a useEffect on the pathname, not from getDerivedStateFromProps.
  • Move to React 18.3.1 with createRoot and the automatic JSX runtime. This removes the classic-runtime workarounds in vite.config.mjs, the global.React setup, and unused import React lines.
  • Move to React Testing Library 16, @testing-library/dom 10 and jest-dom 7. Routes.test.jsx now waits with RTL's waitFor: under vi.waitFor, React 18's act warning for a lazy route fails the Vitest run.
  • Replace react-helmet with react-helmet-async. HelmetProvider wraps the app and any test that renders a <Helmet>.
  • Replace react-ga (Universal Analytics) with react-ga4. The env var becomes VITE_GA_MEASUREMENT_ID, with a placeholder value.
    • gtag's automatic page view is turned off, so there's one page_view per route.
    • A real measurement ID, and any consent banner, still need deciding before deploy.
  • React 19 is not included. It passed every suite but drew the first chart after about 650–700 ms on the production build, against 45–110 ms on React 18. Its 300 ms Suspense reveal throttle stacks on the lazily loaded route and the lazily loaded chart. The architecture doc and the Dependabot React entry record this.
  • Adds docs/execplans/2026-10-26-react-18-upgrade.md.
  • Docs and Dependabot ignores updated to match. The lockfile is regenerated, and d3-transition is still nested under d3@4.

Issue / Bugzilla link

n/a

Testing

Run npm install and npm run build:css first, then npm start.

Please look closely at withFetch.jsx. It now carries every metric fetch on the site.

@stephaniehobson
stephaniehobson changed the base branch from major-updates to deps October 27, 2026 22:50

This branch has not been deployed

No deployments
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