Next.js中如何封装withAuth高阶组件,能否用hooks实现鉴权?
高阶组件 withAuth 实现与报错修复
报错原因
- 类型错误:
React.Component是类组件的基类,不能用于指代所有可渲染的组件类型,需要替换为泛型类型React.ComponentType<P>,同时支持函数组件和类组件。 withAuth is not a function错误:通常是导出导入逻辑不匹配导致,常见触发场景:@/client/components/index文件中未正确导出withAuth- 混淆了命名导出和默认导出的导入写法,默认导出不能加
{}包裹导入变量
修复后的完整withAuth实现
import React, { ComponentType } from 'react' import { useSession } from 'next-auth/react' import { LoginPage } from '@/client/components/index' // 泛型兼容传入组件的所有Props类型 export function withAuth<P extends object>(Component: ComponentType<P>) { const AuthenticatedComponent = (props: P) => { const { data: session, status } = useSession() // 加载状态可替换为自定义加载组件 if (status === 'loading') { return <div>鉴权中...</div> } if (status === 'authenticated' && session) { return <Component {...props} /> } return <LoginPage /> } // 设置displayName方便React DevTools调试 AuthenticatedComponent.displayName = `withAuth(${Component.displayName || Component.name || 'Component'})` return AuthenticatedComponent }
使用方式
和你预期的调用逻辑完全一致:
import { withAuth } from '@/client/components/index' const Homepage = () => { return ( <> <div>Homepage</div> </> ) } export default withAuth(Homepage)
自定义Hook鉴权方案
如果不喜欢HOC的组件嵌套写法,可以用自定义Hook实现更灵活的鉴权逻辑,实现如下:
// hooks/useRequireAuth.ts import { useSession } from 'next-auth/react' import { LoginPage } from '@/client/components/index' export function useRequireAuth() { const { data: session, status } = useSession() return { session, isLoading: status === 'loading', isAuthenticated: status === 'authenticated' && !!session, // 未通过鉴权时直接返回对应的fallback组件,减少样板代码 AuthFallback: status === 'loading' ? <div>鉴权中...</div> : <LoginPage /> } }
使用示例
import { useRequireAuth } from '@/hooks/useRequireAuth' const Homepage = () => { const { isAuthenticated, AuthFallback, session } = useRequireAuth() if (!isAuthenticated) { return AuthFallback } // 可以直接拿到session做业务逻辑 return ( <> <div>欢迎,{session.user?.name}</div> <div>Homepage</div> </> ) } export default Homepage
内容的提问来源于stack exchange,提问作者deadcoder0904
相关产品推荐
相关产品推荐

