I'm trying to determine which modules export React function components vs. regular functions. Bun uses file-based routing, so I can match the request to determine which module file to dynamically import based on the request pathname.
Let's say I have 2 files:
react-route.tsx
:
export default () => {
return <h1>hello, world</h1>
}
api-route.ts
:
export default () => {
return Response.json({ hello: 'world' })
}
I import the module like so in my Bun server:
const router = new Bun.FileSystemRouter({
style: 'nextjs',
dir: './app/routes',
})
const match = router.match(req)
if (!match) {
return new Response('404')
}
const route = await import(match.filePath)
// is route.default a react function component or a regular function?
If route.default
in the example above is a React function, then I want to call renderToString(<route.default />)
and use that for the Bun response. Otherwise, I want to just call route.default()
since it's a normal function.
I've tried using React's isValidElement
but it always returns false. I'm guessing because I'd have to wrap it in a tag first, but if it isn't an actual React function, that will cause problems.
What is the best way to determine if the module's default export function is a React function or just a regular function?
You would not be able to determine the return type of the function at runtime without calling it.
You could attach Symbol
s to the routes to be able to determine the type?
const PAGE_ROUTE = Symbol('PAGE_ROUTE');
type PageFn<T extends unknown> = T & { __routeType: typeof PAGE_ROUTE };
function pageRoute<T extends unknown>(fn: T): PageFn<T> {
const pageFn = fn as PageFn<T>;
pageFn.__routeType = PAGE_ROUTE;
return pageFn;
}
const API_ROUTE = Symbol('API_ROUTE');
type ApiFn<T extends unknown> = T & { __routeType: typeof API_ROUTE };
function apiRoute<T extends unknown>(fn: T): ApiFn<T> {
const apiFn = fn as ApiFn<T>;
apiFn.__routeType = API_ROUTE;
return apiFn;
}
/* ---------------------------------------------------------------------------------------------- */
const page = pageRoute(() => null);
const api = apiRoute(() => null);
[page, api].forEach((fn) => {
if (fn.__routeType === PAGE_ROUTE) {
console.log('Page route');
} else if (fn.__routeType === API_ROUTE) {
console.log('API route');
}
});