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

React在useCallback中调用自定义Hook违反Hooks规则报错如何修复

问题原因

报错的核心原因是React Hooks的调用规则限制:所有Hook必须在React函数组件或者自定义Hook的顶层作用域调用,不能嵌套在回调函数、条件判断、循环等代码块中,你在useCallback的回调里调用useQueryBlablablaAction这个自定义Hook,自然触发了规则校验报错。

解决方案

这里提供两种适配不同场景的修改方案:

方案1:基于现有useQuery逻辑改造(适合需要缓存查询结果的场景)

步骤1:调整自定义Hook支持透传查询配置

给useGraphQLQuery增加配置参数,用来控制是否自动发起请求:

function useGraphQLQuery(
  name,
  query,
  variables = {},
  queryOptions = {}
){
  return useQuery(`bla${name}`, async () => {
    return request(endpoint, query, variables);
  }, queryOptions);
}

同步修改useQueryBlablablaAction支持透传配置:

export function useQueryBlablablaAction(id, queryOptions = {}) {
  return useGraphQLQuery(
    'blablablaAction',
    gql`
      mutation Mutation($ID: String!) {
        blablabla(Input: { ID: $ID }) {
          Status
        }
      }
    `,
    { ID: id },
    queryOptions
  );
}

步骤2:组件顶层调用Hook,手动触发请求

在组件的顶层作用域调用自定义Hook,通过enabled: false禁止组件渲染时自动发起请求,再通过返回的refetch方法在点击时手动触发:

// 组件顶层调用Hook,关闭自动请求,拿到手动触发方法
const { refetch: sendBlablablaRequest } = useQueryBlablablaAction(id, { enabled: false });

// 点击回调里直接调用触发方法
const sendRequest = useCallback(() => {
  sendBlablablaRequest();
}, [sendBlablablaRequest]);

// 按钮绑定逻辑保持不变
<Button variant="contained" onClick={sendRequest}>
  Disable
</Button>

方案2:改用useMutation实现(更适配当前修改类操作的场景)

你当前的操作是GraphQL Mutation(数据修改操作),本身更适合用React Query提供的useMutation实现,不需要额外处理自动请求的逻辑,也更符合语义:

步骤1:封装Mutation专用的自定义Hook

// 新增GraphQL Mutation通用Hook
function useGraphQLMutation(name, mutation) {
  return useMutation(async (variables) => {
    return request(endpoint, mutation, variables);
  }, {
    mutationKey: `bla${name}`
  });
}

// 调整业务Hook用Mutation实现
export function useBlablablaAction() {
  return useGraphQLMutation(
    'blablablaAction',
    gql`
      mutation Mutation($ID: String!) {
        blablabla(Input: { ID: $ID }) {
          Status
        }
      }
    `
  );
}

步骤2:组件内调用

// 组件顶层调用Hook
const { mutate: sendBlablablaRequest } = useBlablablaAction();

// 点击回调触发时传入参数
const sendRequest = useCallback(() => {
  sendBlablablaRequest({ ID: id });
}, [sendBlablablaRequest, id]);

// 按钮绑定逻辑保持不变
<Button variant="contained" onClick={sendRequest}>
  Disable
</Button>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 21:18:02