React 18中useEffect执行两次致OAuth集成重复请求的解决方案
解决方案
针对React 18开发环境下严格模式导致的OAuth回调重复请求问题,以下是几个贴合React特性的优雅处理方式:
1. 使用useRef标记已执行状态
利用useRef在组件卸载重挂载时不会重置的特性,标记是否已经处理过授权回调,避免重复触发API请求:
const IntegrationRedirect: React.FC = () => { const navigate = useNavigate(); const organisationIntegrationsService = useOrganisationIntegrationsService(); const isProcessed = useRef(false); // 标记是否已执行过请求 useEffect(() => { if (!isProcessed.current) { isProcessed.current = true; handleCreateIntegration(); } }, []); const handleCreateIntegration = async (): Promise<void> => { const request: ICreateIntegration = { authorisationCode: '' }; try { const setupIntegrationResponse = await organisationIntegrationsService.createIntegration(request); if (setupIntegrationResponse.data.errors) { throw 'Failed to setup integrations'; } routes.organisation.integrations.navigate(navigate); } catch (error) { // 若需要允许用户重试,可在此重置标记 // isProcessed.current = false; } }; return null; };
该方案仅针对开发环境的严格模式生效,无需修改用户交互流程,也不会影响生产环境的正常逻辑。
2. 让API请求实现幂等性(推荐)
从服务端层面彻底解决问题,将创建集成的POST请求设计为幂等:
- 以授权码作为唯一标识,服务端接收到请求时先检查该授权码是否已被使用
- 若已使用,直接返回成功响应而非错误
- 若未使用,正常执行集成创建流程
这样即使开发环境触发两次请求,第二次也不会返回错误,用户不会看到异常提示,同时生产环境也能规避网络重试等场景下的重复创建问题。
3. 利用路由状态控制执行逻辑
在第三方重定向回应用时,通过路由状态传递未处理标记,处理完成后更新状态,避免重复执行:
const IntegrationRedirect: React.FC = () => { const navigate = useNavigate(); const location = useLocation(); const organisationIntegrationsService = useOrganisationIntegrationsService(); useEffect(() => { // 检查路由状态是否标记为未处理 if (location.state?.processed !== true) { handleCreateIntegration(); } }, [location.state]); const handleCreateIntegration = async (): Promise<void> => { const request: ICreateIntegration = { authorisationCode: location.state?.authorisationCode || '' }; try { const setupIntegrationResponse = await organisationIntegrationsService.createIntegration(request); if (setupIntegrationResponse.data.errors) { throw 'Failed to setup integrations'; } // 跳转时标记状态为已处理,组件重挂载后不会重复执行 routes.organisation.integrations.navigate(navigate, { state: { processed: true } }); } catch (error) { // 处理错误 } }; return null; };
通过路由状态持久化处理标记,即使组件被重挂载,也能根据状态判断是否需要执行请求。
内容的提问来源于stack exchange,提问作者Vuk
相关产品推荐
相关产品推荐

