React-toastify出现重复toast 权限页跳转时单次调用却弹出两次通知
问题原因
- React 18 严格模式重复执行
开发环境下开启<StrictMode>时,React 会故意让组件顶层逻辑、副作用执行两次,用于排查潜在问题。你当前将权限校验、通知触发、重定向逻辑直接写在组件顶层,不属于纯渲染逻辑,两次执行就会触发两次通知生成。你感知到函数仅执行一次,大概率是打点检测方式不准确,没有捕捉到严格模式下的第二次执行。 - ToastContainer 重复挂载
如果应用内同时存在多个<ToastContainer>实例(比如根组件全局挂载了一个,登录页又额外加了一个),同一个toast消息会被两个容器分别渲染,就会出现两条完全相同的通知。 - 重定向时机导致重复触发
调用history.push后组件不会立刻卸载,后续渲染时依然命中权限不足的判断逻辑,会再次触发通知。
解决方案
- 将权限校验逻辑移入
useEffect,保证仅在组件首次挂载后执行一次:
import { useHistory } from "react-router"; import { useEffect } from "react"; import createNotification from "../../../addNotification"; import getRole from "../../../authentication"; const ModHome = () => { const history = useHistory(); const role = getRole(); useEffect(() => { if (!["administrator", "moderator"].includes(role)) { createNotification("You are not a moderator", "error"); history.push("/admin-login"); } }, [history, role]) return ( <div> <h1>Mod page</h1> </div> ) } export default ModHome
- 全局检查
<ToastContainer>的挂载情况,确保整个应用仅挂载一个全局的通知容器,不要在子页面组件中重复添加。 - 若生产环境仍有该问题,可以给toast设置固定ID,避免重复渲染:
修改createNotification函数,支持传入自定义ID,相同ID的通知只会被渲染一次:
// 调用时传入固定ID createNotification("You are not a moderator", "error", "no-mod-permission"); // 修改后的createNotification实现 export default function createNotification(message, type, customId) { const options = { toastId: customId, position: "top-right", autoClose: 5000, hideProgressBar: false, closeOnClick: true, pauseOnHover: true, draggable: true, progress: undefined, }; // 原有类型判断逻辑不变 switch(type) { case "success": toast.success(message, options); break; case "warning": toast.warn(message, options); break; case "error": toast.error(message, options); break; case "info": toast.info(message, options); break; } }
内容的提问来源于stack exchange,提问作者Maypher
相关产品推荐
相关产品推荐

