如何获取手动触发的RTK Query mutation的isLoading状态?
获取手动触发RTK Query Mutation的加载状态
当你通过dispatch(api.endpoints.login.initiate()).unwrap()手动触发mutation时,可以通过以下方式获取isLoading状态,同时避免表单不必要的重渲染:
方法一:通过Redux Selector读取状态
RTK Query为每个endpoint内置了状态selector,你可以直接用useSelector从Redux store中读取mutation的加载状态:
import { useSelector } from 'react-redux'; // 在组件内获取登录mutation的状态 const loginMutationState = useSelector(api.endpoints.login.select()); const isLoginLoading = loginMutationState.isLoading;
loginMutationState对象包含该mutation的全量状态:isLoading、isSuccess、isError、data、error等。如果要避免组件因状态变化重渲染,可以用React.memo包裹表单组件,仅在核心props变化时更新。
方法二:订阅mutation状态变化
initiate方法返回的实例支持订阅状态更新,你可以手动监听并控制局部状态,减少组件重渲染触发:
import { useState, useDispatch } from 'react'; function LoginForm() { const [isLoading, setIsLoading] = useState(false); const dispatch = useDispatch(); const handleLogin = async (credentials) => { const mutation = dispatch(api.endpoints.login.initiate(credentials)); // 订阅状态变化,实时更新loading状态 const unsubscribe = mutation.subscribe((state) => { setIsLoading(state.isLoading); }); try { const data = await mutation.unwrap(); // 处理登录成功逻辑 } catch (error) { // 处理登录错误逻辑 } finally { unsubscribe(); // 取消订阅,避免内存泄漏 } }; return ( <form onSubmit={(e) => { e.preventDefault(); handleLogin({ /* 表单数据 */ }); }}> {/* 表单元素 */} <button type="submit" disabled={isLoading}> {isLoading ? '登录中...' : '登录'} </button> </form> ); }
彻底避免重渲染的方案
如果完全不想触发组件重渲染,可以用useRef直接控制DOM状态,跳过React的状态更新流程:
import { useRef, useDispatch } from 'react'; function LoginForm() { const isLoadingRef = useRef(false); const buttonRef = useRef(null); const dispatch = useDispatch(); const handleLogin = async (credentials) => { // 直接更新DOM状态,不触发组件重渲染 isLoadingRef.current = true; buttonRef.current.disabled = true; buttonRef.current.textContent = '登录中...'; const mutation = dispatch(api.endpoints.login.initiate(credentials)); try { const data = await mutation.unwrap(); // 处理登录成功逻辑 } catch (error) { // 处理登录错误逻辑 } finally { // 恢复DOM状态 isLoadingRef.current = false; buttonRef.current.disabled = false; buttonRef.current.textContent = '登录'; } }; return ( <form onSubmit={(e) => { e.preventDefault(); handleLogin({ /* 表单数据 */ }); }}> {/* 表单元素 */} <button ref={buttonRef} type="submit">登录</button> </form> ); }
内容的提问来源于stack exchange,提问作者E C I N
相关产品推荐
相关产品推荐

