You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native WebView中监听内嵌Calendly组件预约事件的方法

React Native嵌入Calendly监听事件失败的修复方案

问题重现

已将Calendly组件嵌入React Native应用,预约功能正常,但无法监听到组件发出的事件。尝试在injectedJavascript属性和静态HTML中使用postMessage方法,均未成功实现监听。

错误原因

  1. postMessage参数格式错误:React Native WebView的window.ReactNativeWebView.postMessage仅支持传递字符串,直接传递event对象会导致数据无法正确解析
  2. 重复监听冲突:同时在HTML脚本和injectedJavaScript中添加了message事件监听,可能导致逻辑混乱
  3. 事件未过滤:未对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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 10:05:58