useMutation中loading先于onCompleted更新致内容闪烁的解决方案问询
解决Mutation完成前加载状态闪烁的问题
针对你遇到的问题,核心原因是useMutation返回的loading状态会在mutation完成后立即置为false,触发组件重新渲染,之后才执行onCompleted里的跳转逻辑,这中间的渲染就导致了内容闪烁。可以通过以下几种方式解决:
方法一:手动维护加载状态
放弃使用useMutation返回的loading,自己通过useState控制加载状态,确保跳转前加载状态不会提前关闭:
import { useState } from 'react'; import { useNavigate } from '@remix-run/react'; ... const MyComponent = () => { const { redirectTo } = useNavigate(); const [isLoading, setIsLoading] = useState(false); const [mutateFunction] = useMutation(SOME_MUTATION, { onStart: () => setIsLoading(true), onCompleted: () => { // 直接跳转,无需修改isLoading,因为跳转后组件会被卸载 redirectTo('/foo'); }, onError: () => { // 只有出错时才关闭加载状态,避免错误状态下的异常显示 setIsLoading(false); }, }); const handleTriggerMutation = () => { mutateFunction(); }; // 渲染时使用自定义的isLoading控制加载spinner return ( <> {isLoading && <div className="spinner">加载中...</div>} <button onClick={handleTriggerMutation} disabled={isLoading}> 执行操作 </button> </> ); };
方法二:异步调用并直接跳转
通过await调用mutation函数,在mutation完成后立即执行跳转,跳过组件的中间重绘:
import { useNavigate } from '@remix-run/react'; ... const MyComponent = () => { const { redirectTo } = useNavigate(); const [mutateFunction, { loading }] = useMutation(SOME_MUTATION); const handleTriggerMutation = async () => { try { // 等待mutation完成 await mutateFunction(); // 立即执行跳转,此时组件还未触发loading状态更新的重绘 redirectTo('/foo'); } catch (err) { // 处理mutation失败的逻辑 console.error('操作失败:', err); } }; return ( <> {loading && <div className="spinner">加载中...</div>} <button onClick={handleTriggerMutation} disabled={loading}> 执行操作 </button> </> ); };
额外提示
如果你的mutation是服务端操作,推荐直接使用Remix的action函数处理,在服务端完成操作后直接返回redirect,这种方式完全避免客户端的状态更新和渲染问题,是Remix框架下更符合规范的做法。
内容的提问来源于stack exchange,提问作者JoeTidee
相关产品推荐
相关产品推荐

