You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Invalid hook call报错:函数组件不改为类组件如何正常调用异步函数

问题原因定位

首先可以明确,Invalid Hook Call报错确实可能是在函数组件体之外、或异步流程/事件回调中调用Hook触发的。React Hook官方规则明确要求Hook只能在函数组件的最顶层、或自定义Hook的最顶层调用,不允许在循环、条件判断、异步函数、普通工具函数中调用,完全不需要将函数组件改为类组件即可解决。

你当前报错的核心诱因大概率来自以下几个可排查点:

  • 你封装的PasswordApi类的get方法中调用了React Hook:在异步请求流程中调用类方法,等于在组件顶层之外的异步上下文调用Hook,直接违反Hook规则
  • 上下文verifyCodeContext的使用不符合规范:如果你是在getVerificationCode异步函数中调用了useContext获取上下文,也会触发规则报错;直接修改context属性的写法本身也不符合React数据流规范
  • 异步请求没有异常捕获:请求报错后的异常流程可能触发未预料的Hook调用
可行解决方案

1. 排查并修正Api类的Hook使用

如果PasswordApi的底层get方法中用到了useAxios/自定义请求Hook,立刻将Hook的调用逻辑移到函数组件顶层,不要在类方法中使用任何React Hook。如果需要复用请求逻辑,可以将请求逻辑抽为自定义Hook,在组件顶层调用后拿到请求触发函数,再在onSubmit事件中调用触发函数即可。

2. 修正Context使用逻辑

所有Hook(包括useContext)必须在组件最顶层调用,不要在异步函数中调用useContext。同时不要直接修改Context对象的属性,要通过Context对外暴露的更新方法修改数据,避免不触发组件渲染的问题。

3. 补充异步逻辑的异常捕获

给异步请求代码包裹try/catch,避免请求异常溢出导致不可控的代码执行逻辑。

修改后的参考代码
import { useContext } from 'react';

export default function SendVerificationCode({
  route,
  navigation
}: NativeStackScreenProps<
  NativeStackParameterList,
  'SendVerificationCode'
>): JSX.Element {
  // 组件顶层调用useContext获取上下文
  const verifyCodeContext = useContext(VerifyCodeContext);
  // 组件顶层初始化Api实例,不要在事件回调中重复初始化
  const passwordApi = new PasswordApi();

  async function getVerificationCode(
    agencyKey: number,
    username: string,
    email: string,
    verificationCode: string
  ): Promise<void> {
    try {
      const response = await passwordApi.getReset(
        new GetResetRequest({
          agencyKey: agencyKey,
          email: email,
          username: username,
          verificationCode: verificationCode
        })
      );
      // 使用上下文暴露的更新方法修改数据,不要直接修改属性
      verifyCodeContext.setUserName(username);
      navigation.navigate('VerifyCode', {
        copyrightYear: 2021,
        version: '0.0.0.1'
      });
    } catch (err) {
      // 自行补充请求失败的交互提示
      console.error('验证码发送失败', err);
    }
  }

  const onSubmit = (data: any) => {
    getVerificationCode(
      1234,
      data.username,
      data.email,
      '123'
    );
  };

  return (
    <UnauthenticatedTemplate copyrightYear={year} version={version}>
      <Form
        style={styles.form}
        submitText="Send Code"
        onSubmit={onSubmit}
        schema={SendVerificationCodeSchema}
      >
        <FCTextField name="username" placeholder="Username" />
        <FCTextField name="email" placeholder="Email" />
      </Form>
    </UnauthenticatedTemplate>
  );
}

内容的提问来源于stack exchange,提问作者Ackman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 08:54:03