useEffect执行两次致DB重复写入,loading状态异常排查求助
问题排查与解决方案
1. useEffect执行两次的核心原因(非SSR/SSG)
你打印window两次都存在,说明不是服务端渲染导致的——服务端环境根本不存在window对象。这大概率是React 18Strict Mode在开发环境下的刻意行为:它会重复执行useEffect、useState初始化等生命周期钩子,用来帮你检测潜在的副作用问题。
解决方法:
- 开发环境可临时关闭Strict Mode(修改
main.tsx/_app.tsx中的<StrictMode>标签),但上线前建议恢复,它能帮你提前发现隐藏bug。 - 给useEffect添加精准依赖项,同时确保副作用是幂等的:比如用ref标记是否已执行过,或者借助trpc mutation的内置状态控制,避免重复提交。
示例代码(用ref防重复提交):
import { useRef, useEffect } from 'react'; import { trpc } from '../utils/trpc'; const MyComponent = () => { const hasSubmitted = useRef(false); const { mutate, isLoading } = trpc.myMutation.useMutation(); useEffect(() => { if (!hasSubmitted.current) { hasSubmitted.current = true; mutate({ data: 'xxx' }); } }, [mutate]); return <div>{isLoading ? '提交中...' : '已提交'}</div>; };
2. loading状态始终为false的问题
别自己手动维护loading状态了——trpc的mutation自带isLoading状态,直接使用即可。手动维护状态很容易和trpc内部状态不同步,尤其是在Strict Mode重复执行的场景下。
如果使用trpc内置的isLoading仍有问题,排查以下几点:
- 检查mutation调用时机:是否在组件挂载时就触发,但Strict Mode导致第一次调用被React撤销(开发环境下Strict Mode会执行两次副作用,第二次会撤销第一次的效果),导致trpc状态未更新?
- 确认trpc客户端配置:是否开启了
ssr: true但当前是纯客户端组件?若是客户端组件,要确保trpc客户端在客户端环境初始化。
3. 额外注意事项
- 永远不要在useEffect中编写无依赖或依赖不正确的逻辑,这会导致无意义的重复执行。
- 使用trpc mutation时,优先利用它提供的
isLoading、isSuccess、isError等内置状态,避免自行维护状态引发的不一致问题。
内容的提问来源于stack exchange,提问作者RALPH MAALOULY
相关产品推荐
相关产品推荐

