You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断Bun路由模块默认导出是React函数组件还是普通函数?

问题:区分React函数组件与普通函数的最佳方法

我需要区分模块导出的是React函数组件还是普通函数。Bun采用文件路由,可根据请求路径匹配并动态导入对应模块。

假设有两个文件:

react-route.tsx:

export default () => {
    return <h1>hello, world</h1>
}

api-route.ts:

export default () => {
    return Response.json({ hello: 'world' })
}

我在Bun服务器中这样导入模块:

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)

// 如何判断 route.default 是React函数组件还是普通函数?

如果route.default是React函数,我就调用renderToString(<route.default />)生成响应内容;如果是普通函数,则直接调用route.default()。

我尝试过使用React的isValidElement,但始终返回false。猜测是因为需要先将其包裹为标签,但如果它不是真正的React函数,这样做会引发问题。


解决方案

方法一:通过文件扩展名区分(最简单可靠)

React函数组件通常存放在.tsx或.jsx后缀的文件中,而API路由函数一般用.ts或.js。直接通过match.filePath的扩展名判断:

const isReactRoute = match.filePath.endsWith('.tsx') || match.filePath.endsWith('.jsx');

if (isReactRoute) {
  const html = renderToString(<route.default />);
  return new Response(html, { headers: { 'Content-Type': 'text/html' } });
} else {
  const response = await route.default();
  return response;
}

这种方法无需执行函数,性能高且不会有潜在报错,是最推荐的方案。

方法二:通过执行结果判断(兼容复杂场景)

如果无法通过扩展名区分,可以安全执行函数后判断返回值类型:

try {
  const result = await route.default();
  // 判断是否为Response对象
  if (result instanceof Response) {
    return result;
  } 
  // 尝试渲染为React元素
  const html = renderToString(result);
  return new Response(html, { headers: { 'Content-Type': 'text/html' } });
} catch (err) {
  // 如果执行报错,尝试作为React组件渲染
  try {
    const html = renderToString(<route.default />);
    return new Response(html, { headers: { 'Content-Type': 'text/html' } });
  } catch (innerErr) {
    return new Response('Internal Server Error', { status: 500 });
  }
}

方法三:给React组件添加自定义标识

在React组件上添加一个自定义属性,用于标识:

// react-route.tsx
const ReactRoute = () => {
  return <h1>hello, world</h1>;
};
ReactRoute.isReactComponent = true;
export default ReactRoute;

然后在服务器中直接判断该属性:

const defaultExport = route.default;
if (defaultExport.isReactComponent) {
  const html = renderToString(<defaultExport />);
  return new Response(html, { headers: { 'Content-Type': 'text/html' } });
} else {
  const response = await defaultExport();
  return response;
}

这种方法需要修改组件代码,但判断逻辑最直接。


内容的提问来源于stack exchange,提问作者jdion84

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 13:52:43