RTK Query提交mutation后首次isSuccess为false问题排查
问题根因
这是React闭包与状态更新机制导致的正常现象,不是RTK Query的bug:
isSuccess是mutation hook返回的响应式状态,值的更新依赖组件重渲染- 提交回调
onSubmit中捕获的isSuccess是函数创建时的闭包旧值。await postCredentials()执行完成后,虽然RTK Query内部已经标记请求成功,但这个状态变更需要等待组件重渲染才能同步到最新值,当前正在执行的onSubmit回调里拿到的永远是提交前的初始值false - 第二次点击提交时,组件已经因第一次请求成功完成重渲染,新的
onSubmit闭包捕获到了更新后的isSuccess = true,才会打印出预期结果。
正确写法
不要在提交回调中依赖闭包捕获的isSuccess判断请求结果。mutation触发函数postCredentials在await后本身就会返回请求的终态结果,直接判断该返回值即可:
const Login = () => { const { register, handleSubmit, watch, formState: { errors }, } = useForm(); const [postCredentials] = useLoginMutation(); const dispatch = useDispatch(); const onSubmit = async (data: any) => { try { // 调用unwrap()拆解结果:请求成功时返回响应数据,失败时抛出异常 const response = await postCredentials({ username: data.username, password: data.password, }).unwrap(); // 代码走到此处即代表请求成功,可直接执行后续逻辑 dispatch(setUserStatus({ isLoggedIn: true })); console.log('登录请求成功', response); } catch (error) { // 此处处理请求失败逻辑 console.error('登录请求失败', error); } }; return ( // 原有表单渲染逻辑 <form onSubmit={handleSubmit(onSubmit)}>{/* 表单项 */}</form> ) }
可选替代方案
如果需要基于isSuccess状态执行全局副作用,可以通过useEffect监听状态变化,不要在提交回调中读取闭包值:
const [postCredentials, { isSuccess }] = useLoginMutation(); const dispatch = useDispatch(); useEffect(() => { if (isSuccess) { dispatch(setUserStatus({ isLoggedIn: true })); } }, [isSuccess, dispatch]);
注意:该方案需要额外处理多次提交导致的副作用重复触发问题,建议优先使用前一种直接判断trigger返回值的写法。
内容的提问来源于stack exchange,提问作者Ian Leggett
相关产品推荐
相关产品推荐

