繁体   English   中英

如何重构 React 钩子以便我可以在回调中调用它?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM