| One of the worst things about Next.js, Remix etc. is their file system driven routes. I really wish these frameworks would stop relying so much on hidden magic. Conventions are good, but as to why those conventions aren't in code is quite peculiar. Previously, I wrote my route definitions with types for both path params and query params in one file, and used TypeScript to enforce that the equivalent back-end definitions (async loaders etc.) and front-end definitions (React components) were kept in sync. When I first implemented this in a previous project, I found many instances where routes were expecting query params but they were being dropped off (e.g. post login redirects). Supporting things like parameters for nested routes certainly means the TS types themselves are non-trivial, but they're the kind of thing you write (and document) once, but benefit from daily. Examples of stuff that can and should be 100% type checked: // ...
template: {
path: idPath("/template"),
subroutes: {
edit: { path: () => "/edit" },
remix: { path: () => "/remix" },
},
},
onboarding: {
path: () => "/onboarding",
query: (params: { referralCode?: string }) => params,
subroutes: {
createYourAvatar: { path: () => "/createyouravatar" },
},
},
// ...
Routing: // Path params
navigate(routes.template.edit({ id: props.masterEdit.masterEditId }));
// No path params, just query params (null path params)
navigate(routes.onboarding(null, { referralCode }))
// Nested route with query params (inherited from parent route)
navigate(routes.onboarding.createYourAvatar(null, { referralCode }))
React hooks: // Path params
const { id } = useRouteParams(routes.template.edit)
// Query params
const { referralCode } = useRouteQueryParams(routes.onboarding);
API routes: // ...
play: {
path: () => "/play",
subroutes: {
episode: {
path: idPath("/episode"),
},
},
},
// ...
Relative route paths (for defining nested express routers): const routes = relativeApiRoutes.api.account;
router.post(routes.episode(), async (req: express.Request, res: express.Response) => {
|