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

使用react-query封装自动保存Hook时触发Hook使用规则报错如何解决

问题根本原因
  • 违反了React官方规定的Hook使用规则:所有React Hook(包括react-query提供的useMutation)仅允许在React函数组件顶层作用域或者自定义Hook的顶层作用域调用,禁止在嵌套函数、回调函数、事件处理函数、条件语句、循环语句内调用。
  • 你的代码中将useMutation放在了useCallback包裹的fetcher函数内部,而fetcher是组件渲染完成后由事件触发执行的普通函数,不属于Hook允许的调用上下文,因此触发规则校验报错。
修复方案

将useMutation移动到useAutoSave自定义Hook的顶层作用域,fetcher函数内仅调用mutation实例的mutate方法触发请求即可,修复后的代码如下:

export const useAutoSave = () => {
  // useMutation移到Hook顶层,符合调用规则
  const handleSaveSourceDetailsMutation = useMutation(
    ({ saveUrl, data }: { saveUrl: string; data: ISourceConfigurationEdit }) =>
      saveUrl
        ? postSaveStageRaw(`${POST_SAVE_STAGE_RAW}?${saveUrl}`, data)
        : saveSourceDetails(data),
    {
      onSuccess: (data) => {
        const sourceId = sessionStorage.getItem('sourceId');
        queryClient.setQueryData(
          ['getSourcesDetail', Number(sourceId)],
          data,
        );
      }
    }
  );

  const fetcher = useCallback(
    (
      moduleName: ISourceLoaderEditTabs,
      value: Partial<ISourceConfigurationEdit[ISourceLoaderEditTabs]>,
      saveUrl = '',
    ) => {
      const sourceId = sessionStorage.getItem('sourceId');
      const sourceDetail = queryClient.getQueryData([
        'getSourcesDetail',
        Number(sourceId),
      ]) as ISourceConfigurationEdit;

      // 直接调用mutate方法触发请求
      handleSaveSourceDetailsMutation.mutate({
        saveUrl,
        data: {
          ...sourceDetail,
          [moduleName]: {
            ...sourceDetail[moduleName],
            ...value,
          },
        }
      });
    },
    [handleSaveSourceDetailsMutation],
  );

  return [fetcher] as const;
};

修复后组件侧的调用逻辑不需要做任何修改,还可以根据业务需要,将mutation的isLoading、error等状态随fetcher一起返回,方便组件层使用请求状态做交互展示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 15:45:04