Does tanstack router not promote potentially harmful conventions?
The
useSearch and useParams hooks that exist on the Route instances could be promoting a harmful convention.
Since all Route instances must have a runtime reference to their parents, using the hooks via the Route instances means that any hook consumer will have to effectively depend on the entire route tree.
Here's an example of what I find problematic:
The code above will practically hard couple all components that use hooks this way to the entire application, if done consistently. If anyone imports MyRouteComponent.ts, they will also indirectly be importing the entire route tree since the component depends on routes.ts. This can easily make it problematic to run components in isolation, i.e. in storybook or unit tests.
To avoid this problem, I just built my first app using tanstack router and decided to abstract away the useSearch and useNavigate calls and instead loose couple routes and route components via props.
You can see my approach here: https://github.com/kasper573/yas/tree/master/libraries/yas-router#enhanced-route-components
Would love to hear what you guys think of this problem and my solution!GitHub
yas/libraries/yas-router at master · kasper573/yas
Yet Another Stack. Contribute to kasper573/yas development by creating an account on GitHub.
13 Replies
foreign-sapphire•2y ago
there already exists such a thing: https://tanstack.com/router/v1/docs/api/router/RouteApiClass
RouteApi class | TanStack Router Docs
The RouteApi class provides type-safe version of common hooks like useParams, useLoaderData, useRouteContext, and useSearch that are pre-bound to a specific route ID and corresponding registered route types.
RouteApi constructor
conventional-tanOP•2y ago
Are you sure that's what I'm referring to? Maybe I'm missing something, but it doesn't look like that can be used from a component without having access to the route instance.
foreign-sapphire•2y ago
see e.g. https://github.com/TanStack/router/blob/main/examples/react/basic-file-based-codesplitting/src/routes/posts.%24postId/component.tsx#L4
you pass in the route id and don't need the route instance
GitHub
router/examples/react/basic-file-based-codesplitting/src/routes/pos...
🤖 Fully typesafe Router for React (and friends) w/ built-in caching, 1st class search-param APIs, client-side cache integration and isomorphic rendering. - TanStack/router
conventional-tanOP•2y ago
Oh I see! Thanks for clarifying. Yes, that does indeed solve the problem 🙂
Great work!
foreign-sapphire•2y ago
btw, you can also use the "global" hooks like this
useSearch({from: '/route-id'})conventional-tanOP•2y ago
Do you happen to know how it behaves in isolation? If I render the component using the RouteApi instance inside of a router that doesn't have access that that particular route?
foreign-sapphire•2y ago
how would the router not have access to that route?
conventional-tanOP•2y ago
in a unit test
foreign-sapphire•2y ago
it must have when building the routeTree
conventional-tanOP•2y ago
a common use case is to render a page in a unit test, knowing that their links may not be functional since we're outside the router, but we still want to test the rest of the page functionality.
if the page component crashes due to the router hook not being able to do it's thing, that's the type of issue I'm talking about
foreign-sapphire•2y ago
sorry don't know how it would behave in this setup, you need to test this
conventional-tanOP•2y ago
all right! I'll test with the RouteApi, and if I find any problems I'll make a sandbox with a repro! Thanks for the speedy response 🙂
automatic-azure•2y ago
currently I handle hard errors within Storybook context like this:
Is there a more elegant solution lets say to set {strict:false} in case of Storybook context for all
useSearch hooks?