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

如何修复在useCallback中调用自定义Hook的Linter报错问题?

修复useCallback中调用自定义Hook的Linter错误

问题原因

你遇到的Linter错误是违反了React Hook的核心规则:所有Hook必须在组件的顶层作用域调用,不能嵌套在事件回调、条件判断、循环或其他函数内部。useCustomHookSample作为自定义Hook,被放在useCallback包裹的handleSubmit回调里调用,完全不符合Hook的调用规范。


修复方案

根据你的需求(在子组件触发的Submit操作中执行API请求),提供两种可行的修复方式:

方案1:将自定义Hook重构为普通异步函数

如果你的useCustomHookSample只是单纯封装了POST请求逻辑,没有依赖React的Hook特性(比如useState、useEffect等),直接把它改成普通的异步函数即可:

// 替换原来的自定义Hook为普通函数
const customApiRequest = async (param1, param2, param3) => {
  const response = await fetch('/your-api-endpoint', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ param1, param2, param3 })
  });

  if (!response.ok) {
    throw new Error(`请求失败: ${response.statusText}`);
  }

  return response.json();
};

// 父组件中使用
const ParentComponent: FC = () => {
  const [isLoading, setIsLoading] = React.useState(false);

  const handleSubmit = React.useCallback(async () => {
    setIsLoading(true);

    if (!param1 || !param2 || !param3) {
      setIsLoading(false);
      return;
    }

    try {
      // 调用普通异步函数而非Hook
      const response = await customApiRequest(param1, param2, param3);
      setIsLoading(false);
      // 处理返回结果
    } catch (error) {
      setIsLoading(false);
      // 处理错误
    }
  }, [param1, param2, param3]);

  return (
    <>
      <ChildrenComponent handleSubmit={handleSubmit} />
    </>
  );
};

方案2:调整自定义Hook返回触发请求的函数

如果useCustomHookSample内部必须依赖React Hook(比如需要管理请求状态、缓存等),则修改Hook的设计,让它返回一个可以触发请求的函数,而非直接执行请求:

// 调整后的自定义Hook
const useCustomHookSample = () => {
  const [requestData, setRequestData] = React.useState(null);
  const [requestError, setRequestError] = React.useState<Error | null>(null);

  // 用useCallback保证函数引用稳定
  const sendRequest = React.useCallback(async (param1, param2, param3) => {
    try {
      setRequestError(null);
      const response = await fetch('/your-api-endpoint', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ param1, param2, param3 })
      });

      if (!response.ok) {
        throw new Error(`请求失败: ${response.statusText}`);
      }

      const data = await response.json();
      setRequestData(data);
      return data;
    } catch (error) {
      setRequestError(error as Error);
      throw error;
    }
  }, []);

  return { sendRequest, requestData, requestError };
};

// 父组件中使用
const ParentComponent: FC = () => {
  const [isLoading, setIsLoading] = React.useState(false);
  // 在组件顶层调用Hook(符合规则)
  const { sendRequest } = useCustomHookSample();

  const handleSubmit = React.useCallback(async () => {
    setIsLoading(true);

    if (!param1 || !param2 || !param3) {
      setIsLoading(false);
      return;
    }

    try {
      // 调用Hook返回的请求函数
      const response = await sendRequest(param1, param2, param3);
      setIsLoading(false);
      // 处理返回结果
    } catch (error) {
      setIsLoading(false);
      // 处理错误
    }
  }, [param1, param2, param3, sendRequest]);

  return (
    <>
      <ChildrenComponent handleSubmit={handleSubmit} />
    </>
  );
};

关键注意点

  • 始终遵守React Hook规则:Hook只能在组件顶层或其他自定义Hook中调用,确保调用顺序稳定。
  • 如果使用方案2,务必用useCallback包裹Hook内部的请求函数,避免因函数引用变化导致handleSubmit频繁重新创建。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 22:01:02