You need to enable JavaScript to run this app. Antd Notification组件同时弹出两个通知弹窗的原因咨询
优惠活动
大模型
产品
解决方案
定价
更多

Antd Notification组件同时弹出两个通知弹窗的原因咨询

双弹窗异常根因
  • 自定义Notification组件存在副作用执行错位的核心问题,违反了React函数组件的纯渲染规则:
    函数组件的渲染流程应该只负责计算可渲染的JSX,不能在渲染执行过程中直接触发外部副作用(弹通知、调用setState修改父组件状态)。你直接把命令式的notification[type]()调用、父组件的状态清空逻辑clearMsg()塞在组件的渲染返回值里,意味着只要组件进入渲染流程,就会同步执行「弹出通知」「清空错误状态触发组件重渲染」的流程。
  • React18 严格模式(StrictMode)的开发环境检测机制会放大这个问题:
    开发环境下React为了定位隐式副作用,会对所有函数组件执行两遍渲染逻辑、模拟挂载-卸载-重挂载的流程。本身错位的逻辑在单遍渲染时就会触发一次弹窗,双检测机制下直接触发两次弹窗,最终表现为一次操作弹出两个通知。
  • 附带的无效逻辑:notification[type]的返回值是通知实例对象,不是可渲染的JSX元素,直接把它塞在<div>里当子元素渲染,虽然不会直接导致双弹窗,但会触发React的渲染警告,提升逻辑异常概率。
修复方案
  • 将所有副作用逻辑从渲染函数体移至useEffect钩子,和渲染流程彻底解耦:
    import { notification } from "antd";
    import { useEffect } from 'react';
    
    const Notification = ({ msg, type, clearMsg }) => {
      // 仅在依赖项变化时执行一次弹窗逻辑
      useEffect(() => {
        notification[type]({
          description: msg,
        });
    
        // 用延迟函数替代渲染期同步调用clearMsg,避免打断React的渲染调度
        const clearTimer = setTimeout(() => {
          clearMsg();
        }, 0);
    
        // 组件卸载时清理定时器
        return () => clearTimeout(clearTimer);
      }, [msg, type, clearMsg]);
    
      // 命令式Notification会自动挂载到全局容器,组件本身不需要返回DOM
      return null;
    };
    
    export default Notification;
    
  • 用useCallback缓存clearMsg的函数引用,避免父组件每次重渲染生成新的函数引用,触发useEffect无意义重复执行:
    // 父组件中的状态清理逻辑
    const clearMsg = useCallback(() => {
      setError({ state: false, msg: "" });
    }, []);
    
  • 生产环境不受严格模式双渲染检测的影响,只要将副作用逻辑移到正确位置,双弹窗问题就会完全消失;开发环境下也可以临时关闭StrictMode验证逻辑正确性。
  • 如果使用Antd 5.x版本,推荐用App组件包裹根应用,通过App.useApp()获取带全局上下文的Notification实例,避免直接调用全局API带来的配置丢失、重复触发问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.02 09:36:02