我正在开发一个 React 应用程序,很多(但不是全部)页面都包含此代码:
export default function MyPage() {
const { isAuthenticated, loginWithRedirect } = useAuth0<User>();
const handleSignIn = async () => {
await auth.login(loginWithRedirect);
};
if (!isAuthenticated) {
return <SignIn onSignIn={handleSignIn} />;
}
// ...
}
寻求一些有关如何重构此内容的建议,以便它不会在多个页面上重复。钩子合适吗?或者某种父组件包装器???
您看过内置的 HOC withAuthenticationRequired 吗?
如果您需要更多自定义,您可以有效地重新创建
withAuthenticationRequired
,但可以更多地自定义它:
组件包装器效果很好:
const RequiresAuthenticatedUser = ({children}) => {
const { isAuthenticated, isLoading, error, loginWithRedirect } = useAuth0<User>();
const shouldRequireLogin = !isLoading && !isAuthenticated && !error
useEffect(() => {
if(!shouldRequireLogin) return;
auth.login(loginWithRedirect)
},[shouldRequireLogin,loginWithRedirect])
if(error) {
// something went wrong, return an error message
return <>Error</>
}
if(isLoading) {
return null; // or a spinner, I think null is appropriate
}
if(!isAuthenticated) {
auth.login(loginWithRedirect)
return nulll;
}
return <>{children}</>
}
可以这样使用:
function MyPage() {
...
}
export default () => <RequiresAuthenticatedUser><MyPage/></RequiresAuthenticatedUser/>
您可以使用上面的内容创建一个漂亮的小 HOC 来包装您的组件:
const requiresAuthenticatedUser = (Cmp) => (props) => <RequiresAuthenticatedUser><Cmp {...props}/></RequiredAuthenticatedUser>
function MyPage() {
...
}
export default requiresAuthenticatedUser(MyPage)
我强烈提倡使用包装组件(或 HOC)而不是挂钩的一个原因是,它将“我是否有用户”的逻辑问题移到了需要用户的组件之外。否则,“我不确定我是否有用户”的逻辑污染组件是非常常见的,而这些组件实际上只应该关心渲染他们知道自己拥有的用户。