T
TanStack•10mo ago
afraid-scarlet

How to reuse a child routes

#react-router I have a route like this: -
company.$id.members
company.$id.members
// will show members of $id company -
members
members
// will show all members The members route will render the same component
<Members />
<Members />
, it just uses different parameters to fetch. This is just a small sample, there are many similar route reuse cases for me.
7 Replies
sensitive-blue
sensitive-blue•10mo ago
Make a common component, I usually do something like
src/
components/
pages/
SomePage/
index.tsx
route-options.ts // Common route options
src/
components/
pages/
SomePage/
index.tsx
route-options.ts // Common route options
then for typing
// SomePage/index.tsx
export type SomePageProps = {
from: '/' | '/$someParam'; // Union of routes where this page can be mounted
someParam?: number;
getSomeLinkOptions?: (someParam?: number) => LinkOptions; // Get link options to use with navigate() or <Link />, useful if, for example, you have a list page and need to get the link options for the add or edit pages
}

const SomePage = (props: SomePageProps) => {
const { from, someParam } = props

const search = useSearch({ from })

// Get react query options
const queryOptions = !someParam
? getQueryOptionsWithoutParam({ filter: search })
: getQueryOptionsWithParam({ param: someParam, filter: search })

const query = useSuspenseQuery(queryOptions)

return // ...
}

// SomePage/route-options.ts
export type SomePageRouteOptions = {
context: RouterContext; // RouterContext you defined and passed to createRootRouteWithContext;
params: {
someParam?: number
}
}

const getRouteOptions = () => ({ // This is useful to be a function in case you need to pass some arguments to change behavior
beforeLoad: (options: SomePageRouteOptions) => {}
})

export default getRouteOptions

// in a route file
export const Route = createFileRoute('...')({
...getRouteOptions(),
component: MyRoute,
})

function MyRoute() {
const { someParam } = Route.useParams()

return <SomePage from={Route.fullPath} someParam={someParam} />
}
// SomePage/index.tsx
export type SomePageProps = {
from: '/' | '/$someParam'; // Union of routes where this page can be mounted
someParam?: number;
getSomeLinkOptions?: (someParam?: number) => LinkOptions; // Get link options to use with navigate() or <Link />, useful if, for example, you have a list page and need to get the link options for the add or edit pages
}

const SomePage = (props: SomePageProps) => {
const { from, someParam } = props

const search = useSearch({ from })

// Get react query options
const queryOptions = !someParam
? getQueryOptionsWithoutParam({ filter: search })
: getQueryOptionsWithParam({ param: someParam, filter: search })

const query = useSuspenseQuery(queryOptions)

return // ...
}

// SomePage/route-options.ts
export type SomePageRouteOptions = {
context: RouterContext; // RouterContext you defined and passed to createRootRouteWithContext;
params: {
someParam?: number
}
}

const getRouteOptions = () => ({ // This is useful to be a function in case you need to pass some arguments to change behavior
beforeLoad: (options: SomePageRouteOptions) => {}
})

export default getRouteOptions

// in a route file
export const Route = createFileRoute('...')({
...getRouteOptions(),
component: MyRoute,
})

function MyRoute() {
const { someParam } = Route.useParams()

return <SomePage from={Route.fullPath} someParam={someParam} />
}
consider the above pseudocode, that's just an example of how to do this
afraid-scarlet
afraid-scarletOP•10mo ago
I think I know what to do, thanks 🙂
conscious-sapphire
conscious-sapphire•10mo ago
i believe this may be what you are looking for https://tanstack.com/router/latest/docs/framework/react/guide/type-safety#what-if-i-dont-know-the-route-or-its-a-shared-component-and-i-cant-pass-from if you create a shared component you can use something like const data = useLoaderData({strict: false}) and get the loader data from the closest parent route
Type Safety | TanStack Router React Docs
TanStack Router is built to be as type-safe as possible within the limits of the TypeScript compiler and runtime. This means that it's not only written in TypeScript, but that it also fully infers the...
afraid-scarlet
afraid-scarletOP•10mo ago
In fact, I'm confused about using navigate in common components. useSearch and useParams can simply skip ts verification through strict. But navigate's from is not only a ts verification issue, it also involves the correct route path.
conscious-sapphire
conscious-sapphire•10mo ago
Can you provide an example? useNavigate's opts.from should be optional
afraid-scarlet
afraid-scarletOP•10mo ago
I tried to change my thinking. I think I might have thought too complicated before.
conscious-sapphire
conscious-sapphire•10mo ago
cool did you get it worked out?

Did you find this page helpful?