React中如何将useQuery作为点击事件回调,解决Hook非法调用报错
错误原因
React Hook 有严格的调用规则,useQuery 是 React Query 提供的Hook,仅允许在函数组件/自定义Hook的最顶层作用域调用,你把它嵌套在点击事件的回调函数内部,不符合Hook调用规则,所以触发了报错。
另外你的场景是提交创建留言的写操作,本身就不应该使用设计为查询场景的useQuery,更适合用useMutation实现。
解决方案
方案1:使用useMutation实现(推荐,适配写操作场景)
useMutation 是 React Query 专门为增删改类的写操作设计的API,支持手动触发,符合你的需求。
代码示例:
// 组件顶层导入,v4/v5版本从@tanstack/react-query导入,旧版本从react-query导入 import { useMutation } from '@tanstack/react-query'; function 你的组件名() { // 组件顶层作用域声明mutation const createGuestBookMutation = useMutation({ // 实际发起请求的逻辑 mutationFn: async (content) => { return await GuestApi.fetchGuestBookWrite({ spaceUid: 2, bookText: content, }); }, // 请求成功回调 onSuccess: (data) => { console.log('data::::::::::', data); // 可在这里补充成功后的逻辑,比如清空输入框、刷新留言列表等 }, // 请求失败回调 onError: (error) => { console.error('留言提交失败', error); } }); // 点击事件回调,直接触发mutation const createGuestBookWrite = () => { createGuestBookMutation.mutate(content); }; // 其他组件逻辑... return ( <span onClick={createGuestBookWrite}> <TextButton textID={I18N_CODE.GUESTBOOK_NEW_PUBLICATION}></TextButton> </span> ) }
方案2:useQuery手动触发(仅适用于查询类场景,不推荐写操作用)
如果你确实需要用useQuery实现手动触发,可以把useQuery声明在组件顶层,关闭自动触发开关,点击时调用refetch手动发起请求:
import { useQuery } from '@tanstack/react-query'; function 你的组件名() { const { data, error, refetch } = useQuery({ queryKey: [GuestApi.ACTIONS.CREATE_GUEST_BOOK], queryFn: async () => { return await GuestApi.fetchGuestBookWrite({ spaceUid: 2, bookText: content, }); }, enabled: false, // 关闭组件初始化时自动发起请求的逻辑 }); const createGuestBookWrite = () => { refetch(); // 点击时手动触发请求 }; // 其他逻辑... }
注意事项
- 所有React Hook都必须遵守调用规则:仅能在函数组件、自定义Hook的最顶层调用,不能嵌套在回调、条件判断、循环内部
- 增删改类的写操作优先使用
useMutation,useQuery自带的缓存、自动重连、轮询等逻辑是为查询场景设计的,用于写操作容易出现意料之外的问题
内容的提问来源于stack exchange,提问作者quakka-ju
相关产品推荐
相关产品推荐

