Skip to content

Conversation

@jong-kyung
Copy link
Contributor

@jong-kyung jong-kyung commented Jan 15, 2026

fixes #6385

This PR fixes issue #6385, where useParams({ strict: false }) in a parent route would return unparsed parameter values from a child route.

The Fix

The fix the issue by ensuring that parsed parameters from child routes are correctly propagated to their parents when strict: false is used.

  1. Correct Parameter Propagation: The router's internal matching logic was updated. When a route match is being processed, it now correctly looks up the previous match's state, which includes its parsed parameters, and merges them. This ensures the parsed values are available throughout the route hierarchy.

  2. Performance Optimization: As part of the fix, the mechanism for retrieving previous route matches was optimized. The implementation was changed from using Array.prototype.find() to a Map-based lookup. This improves performance from O(n) to O(1), which is especially beneficial in applications with many routes.

Changes

  • packages/router-core/src/router.ts: Updated the core routing logic to correctly handle parameter propagation and implemented the Map-based optimization for match retrieval.
  • packages/react-router/tests/useParams.test.tsx: Added a new unit test to specifically verify that useParams({ strict: false }) receives parsed values.
  • e2e/react-router/basic-file-based/**: Added new routes and an e2e test to confirm the fix in a real-world file-based routing scenario.

Summary by CodeRabbit

  • New Features

    • Added a "Parsed params with strict false" page that displays a parsed numeric version param and links to versioned child routes; parent now reads parsed child params non-strictly.
  • Tests

    • Added end-to-end and unit tests verifying non-strict param parsing and correct numeric values across parent→child navigation.
  • Chores

    • Minor routing performance optimization for faster internal lookups.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 15, 2026

📝 Walkthrough

Walkthrough

Adds file-based routes for /params-ps/strict-false and its child /$version (with parse/stringify), new UI links, E2E and unit tests validating useParams({ strict: false }) receives parsed child params after navigation, updates generated route tree, and introduces an optimization in router match lookup.

Changes

Cohort / File(s) Summary
Generated Route Tree
e2e/react-router/basic-file-based/src/routeTree.gen.ts
Registers /params-ps/strict-false and /params-ps/strict-false/$version; adds imports, file-route entries, child-group creation, parent links, and updates FileRoutes mappings and TanStack React Router module augmentation.
New File Routes
e2e/react-router/basic-file-based/src/routes/params-ps/strict-false/route.tsx, e2e/react-router/basic-file-based/src/routes/params-ps/strict-false/$version.route.tsx
Adds parent route using useParams({ strict: false }) and child route at /$version that parses/stringifies version as a number; exports file Route constants and components.
E2E Route UI
e2e/react-router/basic-file-based/src/routes/params-ps/index.tsx
Adds UI block with Links to the new strict-false child route instances (version 1 and 2).
Tests
e2e/react-router/basic-file-based/tests/params.spec.ts, packages/react-router/tests/useParams.test.tsx
New E2E and unit tests asserting parsed child params propagate to parent when using useParams({ strict: false }) after navigation.
Core Router
packages/router-core/src/router.ts
Adds a Map-based lookup (previousMatchesByRouteId) to retrieve previous matches by routeId (optimization) and replaces linear lookup with map access; minor formatting/placement adjustments.

Sequence Diagram(s)

(Skipped — changes are primarily route additions, type mappings, tests, and a localized router optimization that don't require a multi-component sequential visualization.)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • nlynzaad
  • schiller-manuel

Poem

"A rabbit hopped through node and trail,
strict:false hummed and told the tale.
Child version parsed, parent’s heart beat,
numbers danced where strings did meet—
hop, link, route: a joyous trail 🐇"

🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main fix: ensuring useParams returns parsed params when strict is false, which directly addresses the root issue being resolved.
Linked Issues check ✅ Passed All code changes directly implement the linked issue requirements: parameter propagation logic in router.ts, unit tests in useParams.test.tsx, and e2e tests with new routes demonstrating the fix.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing the strict: false parameter parsing issue and include a performance optimization (Map-based lookup) that is directly related to the fix implementation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link

nx-cloud bot commented Jan 15, 2026

View your CI Pipeline Execution ↗ for commit e5ce02e

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 15m 58s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1m 44s View ↗

☁️ Nx Cloud last updated this comment at 2026-01-18 12:16:35 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 15, 2026

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/arktype-adapter@6387

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/eslint-plugin-router@6387

@tanstack/history

npm i https://pkg.pr.new/TanStack/router/@tanstack/history@6387

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/nitro-v2-vite-plugin@6387

@tanstack/react-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router@6387

@tanstack/react-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-devtools@6387

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-router-ssr-query@6387

@tanstack/react-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start@6387

@tanstack/react-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-client@6387

@tanstack/react-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-server@6387

@tanstack/router-cli

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-cli@6387

@tanstack/router-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-core@6387

@tanstack/router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools@6387

@tanstack/router-devtools-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-devtools-core@6387

@tanstack/router-generator

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-generator@6387

@tanstack/router-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-plugin@6387

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-ssr-query-core@6387

@tanstack/router-utils

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-utils@6387

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/TanStack/router/@tanstack/router-vite-plugin@6387

@tanstack/solid-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router@6387

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-devtools@6387

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-router-ssr-query@6387

@tanstack/solid-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start@6387

@tanstack/solid-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-client@6387

@tanstack/solid-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-server@6387

@tanstack/start-client-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-client-core@6387

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-fn-stubs@6387

@tanstack/start-plugin-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-plugin-core@6387

@tanstack/start-server-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-core@6387

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-static-server-functions@6387

@tanstack/start-storage-context

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-storage-context@6387

@tanstack/valibot-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/valibot-adapter@6387

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/TanStack/router/@tanstack/virtual-file-routes@6387

@tanstack/vue-router

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router@6387

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-devtools@6387

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-router-ssr-query@6387

@tanstack/vue-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start@6387

@tanstack/vue-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-client@6387

@tanstack/vue-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-server@6387

@tanstack/zod-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/zod-adapter@6387

commit: e5ce02e

@jong-kyung jong-kyung closed this Jan 15, 2026
@jong-kyung jong-kyung reopened this Jan 15, 2026
@jong-kyung
Copy link
Contributor Author

jong-kyung commented Jan 15, 2026

oops, clicked the wrong button and accidentally closed this! 😅 Reopening now.

Comment on lines +1537 to +1541
// Update the match's params
const previousMatch = previousMatchesByRouteId.get(match.routeId)
match.params = previousMatch
? replaceEqualDeep(previousMatch.params, routeParams)
: routeParams
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe we shouldn't set the match.params in the 1st iteration then? Because it looks like we're now doing the work twice now.

Copy link
Contributor Author

@jong-kyung jong-kyung Jan 18, 2026

Choose a reason for hiding this comment

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

@Sheraff I tried removing the second update, but the regression (#6385) reappeared.

Here is why the second update is necessary:
The router processes matches from Parent to Child. When the Parent match is created in the first loop, the Child hasn't been processed yet, so routeParams doesn't strictly contain the Child's parsed params at that moment.

Since strict: false allows Parents to access Child params, we must update the Parent's match.params after the entire loop finishes (when routeParams is fully populated).

I've optimized it by piggybacking on the existing second loop (used for Context) instead of creating a new one, so the performance impact is minimal.

Please let me know if I misunderstood anything. Thank you!

@jong-kyung jong-kyung force-pushed the fix/router-params branch 4 times, most recently from 695c44a to e5ce02e Compare January 18, 2026 11:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

useParams({ strict: false }) returns unparsed params

2 participants