Ant Design Notification duration 详解:从默认 4.5s 到永不自动关闭的时长控制方案
本文基于 Ant Design 仓库中 notification/demo/duration.md 演示及其配套实现,系统讲解 Notification(全局通知)的自动关闭延时机制:默认值是什么、为什么、如何让通知"永不关闭"(duration: 0 或 duration: false),以及单条通知、Holder 级配置、全局配置三个层级的时长控制与底层源码原理,帮助你正确驾驭消息通知的生命周期。
该 Demo 要解决什么问题
在 components/notification/demo/duration.md 中,官方给出的说明非常凝练:
自定义通知框自动关闭的延时,默认
4.5s,取消自动关闭只要将该值设为0即可。
对应英文原文为:Duration can be used to specify how long the notification stays open. After the duration time elapses, the notification closes automatically. If not specified, default value is 4.5 seconds. If you set the value to 0, the notification box will never close automatically.
它揭示了三件事,也是本文要展开的核心内容:
- Notification 默认会在 4.5 秒后自动关闭;
- 通过传入
duration可以自定义"停留时间",单位为秒; - 将
duration设为0(或false)即可关闭自动关闭行为,通知将一直停留在屏幕上,直到用户手动点击关闭按钮或调用销毁 API。
场景复现:一条"永不关闭"的通知
该演示对应的完整示例代码位于 components/notification/demo/duration.tsx,使用 useNotification 这一 Hook 形态实现,可直接运行复现效果:
import React from 'react';
import { Button, notification } from 'antd';
const App: React.FC = () => {
const [api, contextHolder] = notification.useNotification();
const openNotification = () => {
api.open({
title: 'Notification Title',
description:
'I will never close automatically. This is a purposely very very long description that has many many characters and words.',
duration: 0,
});
};
return (
<>
{contextHolder}
<Button type="primary" onClick={openNotification}>
Open the notification box
</Button>
</>
);
};
export default App;
代码中包含两个值得注意的工程要点:
useNotification的返回值结构:[api, contextHolder]。api是调用入口(open/success/info/warning/error/destroy),而contextHolder必须作为 React 节点渲染到你的组件树中,它负责承载通知弹层与上下文(locale、主题、样式隔离等)。只有同时渲染{contextHolder},api.open()才能真正弹出通知。这一约定同样适用于 App 组件包裹场景下的App.useApp()用法。- 演示文案刻意设计:description 中反复强调 "never close automatically" 以及一段超长描述("a purposely very very long description that has many many characters and words")。这是因为当通知不再自动关闭时,它需要长期驻留界面,长文案能让读者直观验证"长时间停留 + 手动关闭"的实际交互。
点击按钮后,通知右上角的关闭按钮(×)成为唯一主动关闭途径;代码中并未隐藏 closable,因此该通知可被用户手动关闭。
duration 的类型、默认值与取值语义
在 components/notification/interface.ts 中,ArgsProps(即 api.open(config) 的参数类型)对 duration 的定义为:
duration?: number | false;
官方 API 文档(index.en-US.md 与 index.zh-CN.md)给出的说明为:
Time in seconds before Notification is closed. When set to
0orfalse, it will never be closed automatically.
| 取值 | 行为 |
|---|---|
| 不传(默认) | 4.5 秒后自动关闭 |
duration: 4.5 等正数 |
按指定秒数停留后自动关闭 |
duration: 0 |
永不自动关闭,等待用户手动关闭 |
duration: false |
与 0 等价,永不自动关闭 |
负数(如 -1) |
从源码归一化逻辑看会被视为"不自动关闭"(见下文原理章节),实际使用不建议传入负数 |
单位统一为秒。因此在设计时长时,如需 2 分钟展示,应写 duration: 120,仓库中 progress-color.tsx 即使用了 duration: 20 配合进度条演示"较长时间内的关闭进度"。
三个层级设置 duration:单条、Holder 与全局
duration 并不是只能在某一次调用时传入。综合 interface.ts 中 ArgsProps、NotificationConfig、GlobalConfigProps 三份类型定义,可以得到三个设置层级:
① 单条通知级别(最常用):在某次弹通知时直接传入,仅对当前这一条生效。
api.open({
title: '登录成功',
duration: 2, // 仅这一条 2 秒后关闭
});
// 也可结合预设类型方法
api.success({ title: '操作成功', duration: 1.5 });
api.warning({ title: '请注意', duration: 0 }); // 不自动关闭
② Holder 级别(某一容器内的默认值):通过 notification.useNotification(config) 传入,作为该 Holder 下所有通知的默认时长;单条调用若未显式传 duration,则继承此默认值。
const [api, contextHolder] = notification.useNotification({ duration: 6 });
// api.open({ title: 'x' }) 将默认停留 6 秒
仓库测试 components/notification/tests/hooks.test.tsx 中的 'support duration' 用例正是用 notification.useNotification({ duration: 1.5 }) 来验证 Holder 级默认时长生效。
③ 全局级别(静态方法):通过 notification.config(...) 修改全局默认配置。函数式调用 notification.open / notification.success 属于模块级静态方法,底层由 setNotificationGlobalConfig(见 index.tsx)维护的 defaultGlobalConfig 提供默认值。GlobalConfigProps 中同样包含 duration?: number | false:
notification.config({
duration: 8, // 之后所有静态方法弹出的通知默认停留 8 秒
});
notification.open({ title: '通知' }); // 未单独指定时长,采用 8 秒
对应测试位于 components/notification/tests/index.test.tsx,用例 'support config duration' 先调用 notification.config({ duration: 0 }),再 notification.open(...),随后断言通知正常渲染且不会因默认 4.5s 而消失,从而验证全局配置生效。
优先级从高到低为:单条通知配置 > Holder/全局默认配置。静态方法
notification.open在真正弹出前会将defaultGlobalConfig与单条 config 合并(见 index.tsx 的{ ...defaultGlobalConfig, ...task.config })。
底层原理:源码中的 4.5 与 0/false 归一化
4.5 这个默认值并非散落在各业务代码中,而是在 useNotification.tsx 顶部以常量形式定义:
const DEFAULT_DURATION = 4.5;
const DEFAULT_PLACEMENT: NotificationPlacement = 'topRight';
const DEFAULT_STACK_CONFIG = { offset: 8 };
随后在 Holder 组件解构 props 时作为默认值(duration = DEFAULT_DURATION),再经过一段关键归一化逻辑:
const mergedDuration = useMemo(
() => (isNumber(duration) && duration > 0 ? duration : false),
[duration],
);
(见 useNotification.tsx)。这意味着:
- 只有当
duration是数字且大于 0 时,才会把该数值作为自动关闭延时传给底层; 0、负数以及false都会被统一归一化为false,即"不自动关闭"——这也正是官方文档中"设为 0 即取消自动关闭"在代码层的真正落点;mergedDuration最终随useRcNotification({ ..., duration: mergedDuration })传入底层 @rc-component/notification 完成渲染与计时,单条通知展开时restConfig中的duration也会透传覆盖默认值。
从源码结构可以推断:Ant Design 侧负责"默认值注入 + 参数归一化",而真正的定时器、到时移除、动画退场逻辑由 @rc-component/notification 承担,antd 通过 4.5s 默认值 + 0/false → false 的策略对外提供简洁一致的类型契约(number | false),用户无需关心底层两种"不自动关闭"写法(0 与 false)在实现上的细微差别。
实战建议:何时使用 0 / false,以及配套能力
1. 测试与截图场景广泛使用 duration: 0
在 notification/tests/index.test.tsx、hooks.test.tsx 及 semantic.test.tsx 等大量用例中,均以 duration: 0 阻止通知在断言期间自动消失,避免因异步关闭导致测试不稳定。可视化回归与交互演示同样受益于此。
2. 关键操作结果建议保守使用" 长驻" 需要用户确认或包含较长说明文案的通知(如示例中的超长 description),建议关闭自动关闭或用较长时长,保证信息被完整阅读,同时务必保留可手动关闭的按钮(默认关闭按钮存在)。
3. 配合 showProgress 与 pauseOnHover 提升长驻体验
当时长较长(如 progress-color.tsx 的 duration: 20)时,可开启 showProgress 展示关闭倒计时进度条,并利用 pauseOnHover 让鼠标悬停时暂停计时。这两项同样支持 number | false 语义的全局配置,能在"长驻提醒"与"优雅退场"之间取得平衡。
4. 多条"永不关闭"通知会占据屏幕空间
仓库 stack.tsx 中使用 duration: false 叠加消息堆叠(stack)效果,多条长驻通知会持续累积。生产环境建议配合 maxCount 限制同屏数量,或用 api.destroy(key) 在业务条件满足时主动回收指定通知(见 NotificationInstance.destroy,定义于 interface.ts)。
小结
duration 是 Notification 组件最易理解却最常被忽略的配置之一。通过本 Demo 与源码对照可以确认三条结论:
- 默认
4.5秒由常量DEFAULT_DURATION提供,单位为秒; 0与false语义一致——永不自动关闭,交由用户手动关闭;- 时长可在单条调用、
useNotification(config)、notification.config()三个层级配置,优先级逐级降低,底层由isNumber(duration) && duration > 0的统一归一化逻辑兜底。
实际项目中,请结合通知的重要程度选择"短时提醒(1.5s~3s)""中长展示(5s~10s)"或"长驻手动关闭(0 / false)"三种策略,并善用 showProgress、pauseOnHover、maxCount 与 destroy(key) 等配套能力,构建既体贴又不打扰用户的消息体系。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0632
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
video-shotcraftAI宣传片skill,使用 Remotion 制作电影级产品视频:提供106 张镜头配方卡和可复用的视频魔板。适用于 Claude Code 与 Codex以及所有其他智能体Markdown00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python09
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00