Expo环境下使用expo-web-browser时Linking.addEventListener不触发问题
问题原因
- 监听注册时机错误:
WebBrowser.openBrowserAsync是异步阻塞方法,只有当用户手动关闭内置浏览器,或者浏览器跳转到外部应用离开时,该Promise才会resolve。你将Linking.addEventListener写在await语句之后,相当于浏览器关闭后才注册监听,自然无法收到浏览器运行期间的URL回调。 - 事件监听引用不匹配:注册监听时你传入的是匿名箭头函数,移除监听时传入的是
urlChangeHandler,两个函数引用不一致,会导致监听无法正常移除,引发内存泄漏。 - 能力边界误解:
Linking.addEventListener只能监听到其他应用跳回当前应用的deeplink回调,expo-web-browser基于系统原生的Chrome自定义标签/ASWebAuthenticationSession实现,应用层无法直接获取浏览器内部的页面跳转记录,只有当浏览器跳转至你应用的自定义Scheme时才会触发该事件。
修复方案
1. 配置应用自定义Scheme
首先在项目的app.json或app.config.js中添加Scheme配置,示例如下:
{ "expo": { "scheme": "your-custom-scheme" } }
你需要跳转的目标页面,最终回调时要使用your-custom-scheme://xxx格式的链接,才能触发当前应用的Linking事件。如果是在Expo Go环境下开发测试,默认的Scheme为exp://。
2. 调整代码逻辑
将监听注册时机提前到打开浏览器之前,推荐在组件挂载阶段注册,组件卸载时自动移除:
import { useEffect } from 'react'; import * as Linking from 'expo-linking'; import * as WebBrowser from 'expo-web-browser'; // 组件内逻辑 const YourComponent = () => { useEffect(() => { // 组件挂载时注册监听 const subscription = Linking.addEventListener('url', ({ url }) => { urlChangeHandler(url); }); // 组件卸载时移除监听 return () => { subscription.remove(); }; }, []); const buyNowHandler = async () => { try { // 监听注册完成后再打开浏览器 await WebBrowser.openBrowserAsync("https://google.com"); } catch (error) { console.log(error); } }; const urlChangeHandler = (url) => { console.log("收到回调url: ", url); WebBrowser.dismissBrowser(); }; // 其余组件逻辑 }
注意事项
如果你需要获取内置浏览器内部每一次页面跳转的记录,expo-web-browser 不支持该能力,可以改用react-native-webview自行封装自定义内置浏览器,通过onNavigationStateChange属性即可监听所有页面跳转事件。
内容的提问来源于stack exchange,提问作者AndroidDude123
相关产品推荐
相关产品推荐

