React-Admin v5中React严格模式下OIDC登录流程失效求助
解决方案:通过代码修改避免StrictMode下的重复回调执行
这个问题不需要等待react-admin官方修复,你可以通过修改自身代码解决,核心是防止handleCallback方法被重复执行。
问题原因
React StrictMode在开发环境会重复调用某些函数和生命周期方法(比如组件挂载、useEffect回调等),react-admin v5对AuthProvider的回调触发逻辑和v4存在差异,导致handleCallback被执行两次。第一次调用时signinRedirectCallback已经消耗了URL中的state参数,第二次调用自然会抛出"No matching state found in storage"错误。
修复代码
你可以通过添加执行锁,确保handleCallback只处理一次回调请求:
方案1:使用全局变量(适合AuthProvider类或独立函数)
// 全局标记,确保回调只被处理一次 let isCallbackHandled = false; async handleCallback() { const query = window.location.search; if (!query.includes("code=") && !query.includes("state=")) { throw new Error("Failed to handle login callback."); } // 如果已经处理过当前回调,直接返回 if (isCallbackHandled) return; isCallbackHandled = true; try { await OIDCUserManager.signinRedirectCallback(); } catch (error) { // 忽略因重复调用导致的state不存在错误 if (error.message.includes("No matching state found")) { return; } // 抛出其他类型的错误 throw error; } }
方案2:使用useRef(适合组件内的回调逻辑)
如果你的AuthProvider是基于组件实现的,可以用React的useRef存储状态:
import { useRef } from 'react'; // 在组件内部初始化ref const isCallbackHandled = useRef(false); async handleCallback() { const query = window.location.search; if (!query.includes("code=") && !query.includes("state=")) { throw new Error("Failed to handle login callback."); } if (isCallbackHandled.current) return; isCallbackHandled.current = true; try { await OIDCUserManager.signinRedirectCallback(); } catch (error) { if (error.message.includes("No matching state found")) { return; } throw error; } }
额外说明
生产环境下StrictMode不会触发重复调用,所以这个修复不会影响生产环境的正常运行。如果后续react-admin官方优化了AuthProvider的回调触发逻辑,你可以再移除这个锁逻辑,但目前这个方案是最直接有效的解决办法。
内容的提问来源于stack exchange,提问作者Heikkisorsa
相关产品推荐
相关产品推荐

