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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 14:23:16