Raise actionable error for components declaring library react-router-dom

Merged
MA
2mo ago
+95-0

All Submissions:

  • Have you followed the guidelines stated in CONTRIBUTING.md file?
  • Have you checked to ensure there aren't any other open Pull Requests for the desired changed?

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Changes To Core Features:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your core changes, as applicable?
  • Have you successfully ran tests with your changes locally?

Defect

FINDING-010 (MEDIUM) from the 0.9.9a1 pre-release testing round: React Router 8 dropped the react-router-dom re-export package and Reflex no longer installs it (#6854), but a custom component declaring library = "react-router-dom" still fell through the generic custom-library install path. bun add then installed an unpinned react-router-dom@^7, nesting a second React Router 7 copy beside the first-party v8:

  • Dev: the component rendered and navigated with no warning (vite dedupes to the hoisted v8 copy), and the stray dependency was persisted into reflex.lock/package.json — working purely by accident.
  • Prod: the build failed at prerender with the cryptic TypeError: Cannot destructure property 'basename' of React10.useContext(...) as it is null, exit 1, with nothing pointing at the real cause.

Fix

Component._get_imports (reflex-base) now checks the component's merged import contributions — library, lib_dependencies, and add_imports alike — and raises a pointered ValueError when any of them resolves to the removed react-router-dom package. The bare name, versioned forms (react-router-dom@7.18.2), and subpath imports (react-router-dom/server, react-router-dom@7.18.2/server) are all caught; similarly named but distinct packages (e.g. react-router-dom-fork) are not. The error names the offending component and tells the author to use library = "react-router" (or "react-router/dom" for RouterProvider/HydratedRouter), matching the migration documented in the React Router 8 changelog entry:

ValueError: The component `BadDomLink` references `react-router-dom`, but React Router 8 removed the `react-router-dom` package and Reflex no longer installs it. Use `library = "react-router"` instead, or `"react-router/dom"` for `RouterProvider`/`HydratedRouter`.

The check sits in the per-component import-collection chokepoint (before the imports cache is populated), so it fires at compile/collection time in both dev and prod, names the component that declared the library, and costs a single startswith pre-filter per import key. News fragments added under news/ and packages/reflex-base/news/.

Test plan

  • New regression tests in tests/units/components/test_component.py:
    • test_get_imports_rejects_react_router_dom_library (parametrized over the bare, versioned, subpath, and versioned+subpath forms) — all 4 fail with DID NOT RAISE ValueError on unfixed main, pass with the fix.
    • test_get_imports_rejects_react_router_dom_lib_dependency — fails on unfixed main, passes with the fix.
    • test_get_imports_allows_react_router_libraries — react-router, react-router/dom, and react-router-dom-fork remain accepted.
  • uv run pytest tests/units/components tests/units/compiler — 4338 passed; uv run pytest tests/units/test_app.py tests/units/reflex_base — 393 passed.
  • uv run ruff check . and uv run ruff format . clean; uv run pyright reflex tests packages/reflex-base — 0 errors (one pre-existing warning in an untouched file).
  • uv run python scripts/make_pyi.py — no pyi_hashes.json changes.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EMjBXPozsNeQNSBZecNH8x


Generated by Claude Code