T
TanStack16mo ago
correct-apricot

Best practice for route alias?

We have two routes that show the exact same content but their paths will differ, e.g. /playlists/$playlistId /library/$playlistId Is there any best practice to have minimal boilerplate to make this happen? Right now I've defined a PlaylistView component in routes/-shared/PlaylistView.tsx which also exports a re-usable "route config" object for the loader. I still have to define the component: option for each route since I'm referencing the Route.useLoaderData() and the actual route instance differs for the PlaylistView
// routes/-shared/PlaylistView
export const routeConfig = {
staticData: {
meta: 'musicRoute.meta',
},

loader: async ({ params, context }) => {
const musicQuery = selectCapsuleQuery(
context.store.getState(),
params.playlistId,
)
return loadQuery(context.store, musicQuery)
},
} // satisfies ???

export function PlaylistView({ loaderData }) {
const params = useParams({ strict: false }) // anyway to get this typed?
}

// routes/library/$playlistId.tsx
import { createFileRoute } from '@tanstack/react-router'
import { PlaylistView, routeConfig } from 'app/routes/-shared/PlaylistView'

export const Route = createFileRoute('/library/$playlistId')({
component: function RouteComponent() {
const loaderData = Route.useLoaderData()
return <PlaylistView loaderData={loaderData} />
},

...routeConfig,
})
// routes/-shared/PlaylistView
export const routeConfig = {
staticData: {
meta: 'musicRoute.meta',
},

loader: async ({ params, context }) => {
const musicQuery = selectCapsuleQuery(
context.store.getState(),
params.playlistId,
)
return loadQuery(context.store, musicQuery)
},
} // satisfies ???

export function PlaylistView({ loaderData }) {
const params = useParams({ strict: false }) // anyway to get this typed?
}

// routes/library/$playlistId.tsx
import { createFileRoute } from '@tanstack/react-router'
import { PlaylistView, routeConfig } from 'app/routes/-shared/PlaylistView'

export const Route = createFileRoute('/library/$playlistId')({
component: function RouteComponent() {
const loaderData = Route.useLoaderData()
return <PlaylistView loaderData={loaderData} />
},

...routeConfig,
})
Is there any better way to achieve this? Could I get type checking on my routeConfig? I couldn't immediately find any type to use here, e.g. satisfies RouteConfig
2 Replies
correct-apricot
correct-apricotOP16mo ago
Or maybe I just found a great use-case for route masking? I did get this to work:
export const Route = createFileRoute('/library/$playlistId')({
beforeLoad: ({ params }) => {
throw redirect({
to: '/playlists/$playlistId',
params,
mask: {
to: '/library/$playlistId',
params,
},
})
},
})
export const Route = createFileRoute('/library/$playlistId')({
beforeLoad: ({ params }) => {
throw redirect({
to: '/playlists/$playlistId',
params,
mask: {
to: '/library/$playlistId',
params,
},
})
},
})
frail-apricot
frail-apricot16mo ago
we discussed this previously here https://discord.com/channels/719702312431386674/1200515804622487592/1200515806073720924 but no solution is available yet, so your workarounds look feasible

Did you find this page helpful?