如何在弹窗组件中获取RTK Query Mutation接口的Loading状态以控制提交按钮?
嘿,我来帮你理顺这个问题!其实你完全不需要手动在弹窗和表单之间传递loading状态——RTK Query本身就提供了更优雅的方式让弹窗直接获取mutation的状态,咱们一步步来:
方法一:把Mutation调用逻辑提升到弹窗组件(最推荐)
这是最简单直接的方案,既然弹窗需要控制提交按钮的loading状态,那咱们把mutation的实例化放到弹窗里,再把调用函数传给表单就行:
弹窗组件代码修改:
// 直接在弹窗里初始化mutation const [updateMutation, { loading }] = api.useUpdateMutation(); // 渲染表单时,把mutation函数传进去 return ( <Dialog> {/* 用loading直接控制提交按钮状态 */} <SubmitButton disabled={loading} loading={loading}>提交</SubmitButton> <Form onSubmit={updateMutation} /> </Dialog> );
表单组件代码修改:
const Form = ({ onSubmit }) => { const handleSubmit = (formData) => { // 直接调用父组件传过来的mutation函数 onSubmit(formData).unwrap() .then(() => { // 提交成功后的逻辑,比如关闭弹窗 }) .catch((error) => { // 处理错误 }); }; return ( <form onSubmit={(e) => { e.preventDefault(); const formData = getFormData(); // 你的表单数据获取逻辑 handleSubmit(formData); }}> {/* 表单字段 */} </form> ); };
这样一来,弹窗里的loading状态就是RTK Query自动维护的mutation状态,完全不需要手动setLoading,既省心又不会出错(比如之前手动finally设置loading,万一代码抛出异常没走到那一步就会一直loading)。
方法二:通过useSelector直接读取RTK Query的mutation状态(进阶方案)
如果你不想把mutation逻辑提升到弹窗,也可以直接从Redux store里读取mutation的状态。你之前说用useSelector拿到的总是fulfilled,大概率是没找对正确的状态路径或者没匹配到对应的mutation实例。
正确的读取方式是:
import { useSelector } from 'react-redux'; const Dialog = () => { // 从store里找到对应的update mutation的最新状态 const updateMutationState = useSelector(state => { // 遍历所有mutation,找到endpoint名称为'update'的那条 return state.api.mutations.find(mutation => mutation.definition.endpointName === 'update' ); }); // 判断是否处于loading状态 const isLoading = updateMutationState?.status === 'pending'; return ( <Dialog> <SubmitButton disabled={isLoading} loading={isLoading}>提交</SubmitButton> <Form /> </Dialog> ); };
不过这种方法要注意:如果页面上同时有多个相同的mutation请求,find可能会拿到旧的状态,所以需要结合请求参数来精准匹配(比如mutation.meta.arg就是你传给mutation的参数),相对来说复杂度高一些,所以更推荐第一种方法。
为什么你之前的useSelector没拿到正确状态?
RTK Query的mutation状态会存在state.api.mutations数组里,每个mutation条目包含status(pending/fulfilled/rejected)、meta.arg(请求参数)等信息。你之前可能没找到正确的条目,或者在查询时mutation已经完成,所以看到的是fulfilled状态。
备注:内容来源于stack exchange,提问作者Robert Koritnik

