React Native WebView 首次进入报atrium://未知URL scheme错误
问题根因
- 原生WebView组件首次挂载时存在执行时序差:原生层会优先完成实例创建、启动初始
source指定URL的加载流程,之后才会将JS侧注册的导航类回调同步到原生代码层。 - 当前加载的HTTPS目标页面,在页面DOM加载完成后会第一时间触发
atrium://自定义scheme跳转请求,该请求发生在JS拦截回调同步到原生层之前,原生层因未接收到自定义scheme的拦截规则,会按默认未知scheme逻辑抛出UNKNOWN_URL_SCHEME错误。 - 二次进入页面时,原生WebView实例已被路由栈缓存,JS侧的拦截回调早已完成同步注册,触发的自定义scheme请求会被正常拦截,因此不会出现报错。
- 现有代码存在逻辑偏差:
onNavigationStateChange回调无阻断页面加载的能力,仅用于同步导航状态信息,将拦截逻辑放在该回调中本身无法起到拦截作用;真正能阻断请求加载的只有onShouldStartLoadWithRequest回调。
修复方案
- 拆分两个回调的职责,单独实现请求拦截逻辑,不要共用同一个处理函数:
// 仅负责请求拦截,明确对自定义scheme返回false阻断原生加载 const handleShouldStartLoadWithRequest = request => { const { url } = request; if (url.startsWith('atrium://')) { // 执行自定义scheme对应的业务逻辑 return false; } return true; } // 仅负责同步导航状态信息,不做拦截处理 const handleWebViewNavigationStateChange = newNavState => { const { url } = newNavState; console.log("当前加载URL:", url) }
- 调整初始加载流程,规避首次加载的时序差问题:WebView首次挂载时先加载空白占位页,等原生实例完成初始化、所有回调同步注册完成后,再加载目标业务URL。
// 增加状态标记WebView是否完成初始化 const [isWebViewReady, setIsWebViewReady] = useState(false); <WebView setSupportMultipleWindows={false} ref={webView} originWhitelist={['http://*', 'https://*', 'atrium://*']} // 首次挂载先加载空白页,就绪后再加载目标业务地址 source={isWebViewReady ? { uri: route.params.url } : { html: '' }} style={{ flex: 1 }} javaScriptEnabled={true} onNavigationStateChange={handleWebViewNavigationStateChange} onShouldStartLoadWithRequest={handleShouldStartLoadWithRequest} // 收到首次加载启动事件时,标记组件已就绪 onLoadStart={() => { if (!isWebViewReady) setIsWebViewReady(true) }} />
- 补充原生层的scheme识别配置:安卓端需在对应承载WebView的Activity配置中,补充
atrium://scheme的识别规则;iOS端需在应用配置文件中补充对atriumscheme的查询权限,避免原生层未收到JS回调时直接抛出未知scheme错误。
内容的提问来源于stack exchange,提问作者user14740177
相关产品推荐
相关产品推荐

