使用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
相关产品推荐
相关产品推荐

