[英]How to refactor a React hook so that I can call it inside a callback?
我正在处理一些登录代码,并希望添加检查用户是否是管理员的功能。 我知道我不能在回调中调用钩子,并且我已经检查了关于 SO 的其他答案,但仍然无法理解如何使用钩子的功能。 问题是它必须从表单的提交 function 中触发 - 所以我不能在我的 React 组件的顶层调用它,正如错误消息所暗示的那样。 ( React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks
)
谁能帮我弄清楚如何重构此代码以将钩子的功能转换为回调?
代码说明:
SignIn 组件 - 是一个带有onSubmit
function 的表单,它调用自定义的signIn
function。
signIn
- 仅在身份验证流程成功时才调用用户/密码和回调 function。
hook useCheckUserAdmin
- 检查用户是否是管理员。 理想情况下在signIn
的回调中调用。
onSuccess
function - 重定向到管理员或客户端主页。 在signIn
的回调中调用,就在钩子之后。
实际代码:
这是主要的登录组件(注意一些不相关的部分已删除),包括onSuccess
function
const SignInComponent = () => {
const onSuccess = React.useCallback(
(userIsAdmin) => {
// history.replace(etc. etc.) <- some boolean logic to direct to an admin or a regular user page
},
[]
);
return <Formik
onSubmit={async (values) => {
await signIn(values.username, values.password, (userId) => {
const userIsAdmin = useCheckUserAdmin(userId)
onSuccess(userIsAdmin);
setError(null);
}).catch((err) => {
setError(err.message);
});
}}
>
}
自定义钩子useCheckUserAdmin
(为便于阅读而简化):
import { useGetUser } from "../api/composedHooks";
export default function useCheckUserAdmin(userId: string) {
const userQuery = useGetUser({
variables: { id: userId },
});
return userQuery.userType;
}
登录 function:
async function signIn(
username: string,
password: string,
callback: (userId: string) => void
) {
try {
const result = await Auth.signIn({
username,
password,
});
if (result) {
return callback(result.username);
}
} catch (error) {
console.error("error signing in:", error);
throw error;
}
}
真的没有办法在你的回调中调用自定义钩子(因为它没有通过钩子检查规则)。 如果您必须在自定义钩子内执行此逻辑(这可能不是必需的,因为我看不出为什么需要有状态逻辑),一种选择是从自定义钩子返回必要的函数:
SignInComponent = () => {
{setUserId, checkUserIsAdmin} = useCheckUserIsAdmin() // non-conditionally call the hook
}
然后在你的回调中是这样的:
setUserId(user.id)
callback(checkUserIsAdmin)
并且您的钩子重构为将 userId 存储在 state 中:
[userId, setUserId] = useState(null) // or some invalid initial value
const checkUserIsAdmin = () => {...logic operating on userId}
return {setUserId, checkUserIsAdmin}
不确定它是否有帮助,但这是满足问题条件的一种方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.