React Native WebView中监听内嵌Calendly组件预约事件的方法
React Native嵌入Calendly监听事件失败的修复方案
问题重现
已将Calendly组件嵌入React Native应用,预约功能正常,但无法监听到组件发出的事件。尝试在injectedJavascript属性和静态HTML中使用postMessage方法,均未成功实现监听。
错误原因
- postMessage参数格式错误:React Native WebView的
window.ReactNativeWebView.postMessage仅支持传递字符串,直接传递event对象会导致数据无法正确解析 - 重复监听冲突:同时在HTML脚本和
injectedJavaScript中添加了message事件监听,可能导致逻辑混乱 - 事件未过滤:未对Calendly专属事件做过滤,可能接收无关消息干扰
修复后的完整代码
import React, { useRef } from "react" import { StyleSheet, ActivityIndicator } from "react-native" import { WebView } from "react-native-webview" // 过滤Calendly专属事件 function isCalendlyEvent(e) { return e.data.event && e.data.event.indexOf("calendly") === 0 } const BookAppointment = ({ navigation }) => { const webViewRef = useRef(null) const source = { html: ` <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> </head> <div class="calendly-inline-widget" style="min-width:320px;height:100%" data-auto-load="false" id="myHeader"></div> <script type="text/javascript" src="https://assets.calendly.com/assets/external/widget.js"></script> <script> // 初始化Calendly内联组件 Calendly.initInlineWidget({ parentElement: document.getElementById('myHeader'), url: 'https://calendly.com/taranathchimbili/doctor-appointment', prefill: { name: "John Doe", email: "john@doe2.com" }, // 直接通过Calendly的回调监听事件(更可靠) onEvent: function(event) { // 将事件序列化为字符串后传递给React Native window.ReactNativeWebView.postMessage(JSON.stringify(event)); } }); // 兼容方式:监听window的message事件(备用) window.addEventListener("message", function(event) { if (event.data && event.data.event && event.data.event.startsWith('calendly')) { window.ReactNativeWebView.postMessage(JSON.stringify(event.data)); } }); </script>` } const onMessage = (event) => { try { // 解析传递过来的JSON字符串 const eventData = JSON.parse(event.nativeEvent.data); // 过滤并处理Calendly事件 if (isCalendlyEvent({ data: eventData })) { console.log("Calendly事件:", eventData); // 这里可以添加你的业务逻辑,比如预约成功后的跳转、通知等 if (eventData.event === "calendly.event_scheduled") { console.log("预约成功!"); // navigation.navigate('SuccessScreen'); } } } catch (error) { console.error("解析事件失败:", error); } } return ( <WebView ref={webViewRef} originWhitelist={["*"]} source={source} startInLoadingState={true} renderLoading={() => <ActivityIndicator size="large" color="#0000ff" />} onMessage={onMessage} // 移除重复的injectedJavaScript /> ) } export default BookAppointment
关键修改说明
- 使用Calendly官方回调:通过
initInlineWidget的onEvent参数直接绑定事件监听,比监听window message更可靠 - 序列化事件数据:将事件对象转为JSON字符串后再调用
postMessage,确保React Native能正确解析 - 移除重复监听:删除
injectedJavaScript中的重复监听逻辑,避免冲突 - 事件解析与过滤:在
onMessage中解析JSON字符串,并通过isCalendlyEvent过滤有效事件,同时增加异常处理防止解析失败 - 替换Loading组件:原代码中的
Loading组件未导入,替换为React Native内置的ActivityIndicator(可根据实际项目替换)
内容的提问来源于stack exchange,提问作者thedomguy
相关产品推荐
相关产品推荐

