T
TanStack•this hour
rare-sapphire

Code based useParams hook works with pathless id prefixed to route.

My routing tree looks like the following: RootRoute -> Pathless_Layout_Route -> Products -> ViewProductRoute. When i use the useParam hook like this:
const params = useParams({from: "/products/$productId"});
const params = useParams({from: "/products/$productId"});
It will show an error saying that the invariant is not found. Even though when i remove useParams, the page does render.` However when i prefix the route with the pathless layout route, it does work.
const params = useParams({from: "/ui_with_header/products/$productId"});
const params = useParams({from: "/ui_with_header/products/$productId"});
Did i miss something in the documentation? Or is this supposed to happen?
14 Replies
fair-rose
fair-rose•this hour
useParams needs a route id, not a path so you must supply the full id (which in your case includes the layout)
rare-sapphire
rare-sapphireOP•this hour
Okay thanks for clearing up, but did i miss that somewhere in the documentation?
rare-sapphire
rare-sapphireOP•this hour
useParams hook | TanStack Router React Docs
The useParams method returns all of the path parameters that were parsed for the closest match and all of its parent matches. useParams options The useParams hook accepts an optional options object. o...
rare-sapphire
rare-sapphireOP•this hour
Because i was not able to find that out on this page.
fair-rose
fair-rose•this hour
it might not be document we d explicitly. can be improved for sure but you should have gotten a typescript error did you not?
rare-sapphire
rare-sapphireOP•this hour
This is what i see.
No description
No description
rare-sapphire
rare-sapphireOP•this hour
My typescript intellisense is broken. I think i messed up the configuration somewhere a bit. Because i also do not get route auto completes when using navigate hook.
fair-rose
fair-rose•this hour
then fix the typescript setup first 😆
rare-sapphire
rare-sapphireOP•22h ago
After moving some code around and declaring the module i do get intellisense. Which would have indeed prevented the problem in the 1st place.
declare module "@tanstack/react-router" {
interface Register {
router: typeof howDoIGetTypeOfRouterHere?;
}
}
function Router() {
const myContext = useMyContext();
const router = createRouter({
routeTree: Routes,
context: {
someContext: {
...myContext
}
}
});
return <RouterProvider router={router} />;
}
declare module "@tanstack/react-router" {
interface Register {
router: typeof howDoIGetTypeOfRouterHere?;
}
}
function Router() {
const myContext = useMyContext();
const router = createRouter({
routeTree: Routes,
context: {
someContext: {
...myContext
}
}
});
return <RouterProvider router={router} />;
}
Is it possible to instantiate the router in a component, while still being able to use Context.Provider components? Because of this i was not able to then declare the module because router was not in scope anymore + you cannot declare the module in function scope. Or is it a better idea to completely migrate these context components into the Router context? Thanks by the way for all the help. The intellisense does work after refactoring stuff to get the module declaration to work.
fair-rose
fair-rose•22h ago
I would not instantiate the router inside a component what's the use case for that?
rare-sapphire
rare-sapphireOP•22h ago
This project uses a lot of useContext hooks, with Context.Provider components. So underlying components can const someHook = useMyHook These are the .Provider components for that.
<AuthProvider>
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={theme}>
<SnackbarProvider
<AuthProvider>
<QueryClientProvider client={queryClient}>
<ThemeProvider theme={theme}>
<SnackbarProvider
In order to pass this context to the router, so i can use authorization in beforeLoad. I use the hook in a router component so i can pass it to the initial context of the router, otherwise i get key not defined errors when i navigate to pages. The problem with this method was that useAuth for example can only be called in Provider component context, so i had to wrap the router instantiation inside a Router component, with the context Provider components as their parents. Problem was that you now cannot infer the type of router, because its instantiated in component and module block declarations do not work there. At least that was my thought process there.
fair-rose
fair-rose•22h ago
you can supply context via the RouterProvider. also look at Wrap and InnerWrap options
rare-sapphire
rare-sapphireOP•21h ago
function App() {
const auth = useAuth();
console.log(auth.isAuthenticated);
return <RouterProvider router={router} context={{ auth }} />;
}

function Root() {
return (
<StrictMode>
<AppProviders>
<App></App>
</AppProviders>
</StrictMode>
);
}
root.render(Root());
function App() {
const auth = useAuth();
console.log(auth.isAuthenticated);
return <RouterProvider router={router} context={{ auth }} />;
}

function Root() {
return (
<StrictMode>
<AppProviders>
<App></App>
</AppProviders>
</StrictMode>
);
}
root.render(Root());
Final question then i hope to not bother u anymore. Is this the correct way of doing things? When i use Wrap, i still cannot use the useAuth hook to create context, because my provider for useAuth is in AppProviders i tried it but it didnt work. This way everything down the tree can use all the providers, including the router.
fair-rose
fair-rose•16h ago
Wrap works like this: (taken from packages/react-router/src/RouterProvider.tsx)
const provider = (
<routerContext.Provider value={router as AnyRouter}>
{children}
</routerContext.Provider>
)

if (router.options.Wrap) {
return <router.options.Wrap>{provider}</router.options.Wrap>
}
const provider = (
<routerContext.Provider value={router as AnyRouter}>
{children}
</routerContext.Provider>
)

if (router.options.Wrap) {
return <router.options.Wrap>{provider}</router.options.Wrap>
}
So it wraps the RouterProvider, not App in your case. Your impl looks fine!

Did you find this page helpful?