Next.js+TypeScript报错ProtectRoute无法作为JSX组件使用如何解决
Next.js TypeScript 环境下自定义组件报
cannot be used as a JSX component错误 问题现象
在Next.js + TypeScript项目中开发路由保护组件,将组件作为JSX元素引入使用时,TypeScript抛出类型错误:
ProtectRoutecannot be used as a JSX component
报错效果如下:
关联代码
路由保护组件ProtectRoute实现
import { PropsWithChildren } from 'react'; type Props = PropsWithChildren<{}>; export const ProtectRoute = ({ children }: Props) => { const { isAuthenticated, isLoading } = useAuth(); if ( isLoading || (!isAuthenticated && window.location.pathname !== '/login' ) { return <div>Loading...</div>; } return children; };
_app.tsx入口组件使用代码
import type { AppProps } from 'next/app'; import { AuthProvider, ProtectRoute } from '../contexs/auth'; function MyApp({ Component, pageProps }: AppProps) { return ( <AuthProvider> <ProtectRoute> <Component {...pageProps} /> </ProtectRoute> </AuthProvider> ); } export default MyApp;
报错原因
触发该报错的常见原因有三个:
- 组件内部if条件判断存在语法错误:
!isAuthenticated前的左括号没有对应闭合右括号,导致TypeScript无法正确推导组件类型 - 组件返回值类型不符合JSX组件校验规则:直接返回
children时,children的类型为ReactNode,可能包含undefined、boolean等非合法JSX元素类型,无法通过TS类型校验 - 项目依赖存在版本冲突:本地安装了多个版本的
@types/react,导致JSX元素类型校验逻辑不一致
修复方案
- 修正语法错误:补全if条件判断缺失的闭合右括号
- 调整组件返回值:将返回的
children包裹在Fragment(<>...</>)中,保证返回值始终为合法JSX元素;也可以给组件显式标注ReactElement返回值类型 - 排查依赖冲突:如果是多版本
@types/react导致的问题,在package.json中添加resolutions字段强制统一@types/react版本,重新安装依赖即可
修复后的ProtectRoute组件代码
import { PropsWithChildren } from 'react'; import { useAuth } from '../contexs/auth'; type Props = PropsWithChildren<{}>; export const ProtectRoute = ({ children }: Props) => { const { isAuthenticated, isLoading } = useAuth(); // 补全条件判断缺失的闭合括号 if ( isLoading || (!isAuthenticated && window.location.pathname !== '/login') ) { return <div>Loading...</div>; } // 用Fragment包裹children,保证返回值为合法JSX元素 return <>{children}</>; };
依赖冲突修复配置
在package.json中添加如下配置,版本号与项目实际使用的React主版本保持一致即可:
{ "resolutions": { "@types/react": "^18.2.0" } }
添加后删除node_modules目录和包管理锁文件,重新执行依赖安装命令即可生效。
内容的提问来源于stack exchange,提问作者6899 huge
相关产品推荐
相关产品推荐

