React通知组件无法按时自动关闭问题求助
解决React Notification组件用户交互时无法按时自动关闭的问题
当前实现的Notification组件设置了自动关闭时长,但用户与页面交互(如点击按钮、操作元素)时,通知无法在指定时长后关闭,需等待用户停止交互3秒后才会消失。
原因分析
组件的useEffect依赖了duration和onClose,当用户交互导致父组件重新渲染时,Notification组件会随之重新渲染,触发useEffect重新执行——清除原有定时器并创建新的定时器,相当于每次交互都重置了倒计时,导致通知无法按时关闭。
解决方案
使用useRef存储定时器ID,并且让useEffect仅在组件挂载时执行一次(空依赖数组),确保定时器不受组件重新渲染的影响,无论用户是否交互,都会在初始设置的时长后自动关闭通知。
修改后的完整代码
import React, { useEffect, useState, useRef } from "react"; import { IoMdClose } from "react-icons/io"; export type NotificationValueType = { message: string; type: "success" | "error"; }; type NotificationProps = { message: string; type?: "success" | "error" | "warning"; duration?: number; onClose?: () => void; index?: number; }; const Notification: React.FC<NotificationProps> = ({ message, type = "success", duration = 3000, onClose, index = 0, }) => { const [showAlert, setShowAlert] = useState(true); const timerRef = useRef<NodeJS.Timeout | null>(null); let notificationColor = "bg-green-500"; if (type === "error") { notificationColor = "bg-red-500"; } else if (type === "warning") { notificationColor = "bg-orange-400"; } const alertClasses = `${notificationColor} z-50 fixed top-4 left-1/2 text-base transform -translate-x-1/2 max-w-sm w-full text-white p-2 pl-6 rounded-sm flex justify-between items-center`; const dynamicTopClass = `mt-${index * 12}`; useEffect(() => { // 仅在组件挂载时启动一次定时器 timerRef.current = setTimeout(() => { setShowAlert(false); onClose?.(); }, duration); // 组件卸载时清除定时器 return () => { if (timerRef.current) { clearTimeout(timerRef.current); } }; }, []); // 空依赖数组,确保只执行一次 const handleClose = () => { setShowAlert(false); onClose?.(); // 手动关闭时清除定时器 if (timerRef.current) { clearTimeout(timerRef.current); } }; return showAlert ? ( <div className={`${alertClasses} ${dynamicTopClass}`}> <p>{message}</p> <IoMdClose className="cursor-pointer font-extrabold text-xl text-gray-light hover:text-white" onClick={handleClose} /> </div> ) : null; }; export default Notification;
关键修改点
- 新增
useRef存储定时器ID,避免组件重新渲染时丢失定时器引用 - 将
useEffect的依赖数组设为空,确保定时器仅在组件挂载时创建一次 - 新增手动关闭时的定时器清除逻辑,避免内存泄漏
- 优化
onClose调用方式,使用可选链语法简化代码
内容的提问来源于stack exchange,提问作者prajun7
相关产品推荐
相关产品推荐

