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

React FullCalendar弹窗异常求助:编辑与删除弹窗同时显示

FullCalendar点击删除按钮时双弹窗同时显示问题解决

问题背景

使用React + FullCalendar开发带CRUD功能的自定义日历,点击事件卡片内的删除按钮时,已通过setIsDeleteModalOpen(true)和setIsEditModalOpen(false)设置只显示删除弹窗,但编辑弹窗仍会同时弹出。经排查,问题源于点击删除按钮时触发了FullCalendar绑定的eventClick事件(该事件会打开编辑弹窗)。

核心原因:事件冒泡

删除按钮是事件卡片的子元素,点击删除按钮时,事件会向上冒泡到父级的事件卡片元素,触发FullCalendar的eventClick回调handleEventClick。即使在删除按钮的点击回调中关闭了编辑弹窗,handleEventClick里的setIsEditModalOpen(true)会在之后执行,覆盖之前的状态修改,最终导致两个弹窗同时显示。

解决方案

方法1:阻止删除按钮的事件冒泡

在删除按钮的点击事件中调用stopPropagation(),阻止事件向上传递到FullCalendar的事件元素,避免触发eventClick回调:

const renderEventContent = (eventInfo) => {
    return (
        <>
            <b>{eventInfo.timeText}</b>
            <p>{eventInfo.event.title}</p>
            <button onClick={(e) => {
                // 阻止事件冒泡,避免触发FullCalendar的eventClick
                e.stopPropagation();
                setSelectedEvent(eventInfo.event);
                setIsDeleteModalOpen(true);
                setIsEditModalOpen(false);
            }}>X</button>
        </>
    );
};

方法2:在handleEventClick中过滤点击目标

在handleEventClick中判断点击的元素是否为删除按钮,如果是则跳过打开编辑弹窗的逻辑:

const handleEventClick = (arg) => {
    // 仅当点击的不是删除按钮时,才打开编辑弹窗
    if (arg.jsEvent.target.tagName.toLowerCase() !== 'button') {
        setSelectedEvent(arg.event);
        setIsEditModalOpen(true);
    }
};

额外优化建议

可以给删除按钮添加特定类名(如event-delete-btn),让判断逻辑更精准:

// 优化后的handleEventClick
const handleEventClick = (arg) => {
    if (!arg.jsEvent.target.classList.contains('event-delete-btn')) {
        setSelectedEvent(arg.event);
        setIsEditModalOpen(true);
    }
};

对应的按钮代码:

<button className="event-delete-btn" onClick={(e) => {
    e.stopPropagation();
    setSelectedEvent(eventInfo.event);
    setIsDeleteModalOpen(true);
    setIsEditModalOpen(false);
}}>X</button>

内容的提问来源于stack exchange,提问作者Peter_Griffindor

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 21:24:58