React中使用notistack页面跳转时如何正确处理Snackbar?
问题分析
当前Snackbar返回页面后短暂显示即关闭的核心问题在于:
- 两个独立
useEffect共享同一个挂载状态判断,逻辑混乱,卸载时两次调用无参closeSnackbar()(会关闭所有Snackbar),引发状态冲突; - 返回页面时,若数据从缓存获取,挂载判断逻辑导致Snackbar触发时机异常,加上无差别关闭操作,导致刚打开就被关闭。
解决方案
通过合并逻辑、精准控制Snackbar生命周期来修复问题,修改后的ProfilePageStatistics组件代码如下:
import { useEffect, useRef } from 'react'; import { useSnackbar } from 'notistack'; export default function ProfilePageStatistics() { const { data } = userGetStatistics(); // 数据请求Hook const { enqueueSnackbar, closeSnackbar } = useSnackbar(); const snackbarKeys = useRef({ expiring: null, expired: null }); const isFirstMount = useRef(true); const messages = { expiring: 'Less than 15 days remaining', expired: 'Expired', }; useEffect(() => { // 首次挂载时跳过,等待数据加载完成 if (isFirstMount.current) { isFirstMount.current = false; return; } // 先关闭之前打开的对应Snackbar,避免重复堆积 if (snackbarKeys.current.expiring) { closeSnackbar(snackbarKeys.current.expiring); snackbarKeys.current.expiring = null; } if (snackbarKeys.current.expired) { closeSnackbar(snackbarKeys.current.expired); snackbarKeys.current.expired = null; } // 显示需要的Snackbar并保存唯一key if (data?.count15Days) { snackbarKeys.current.expiring = enqueueSnackbar(messages.expiring, { variant: 'certificateStatus', persist: true, }); } if (data?.countExpired) { snackbarKeys.current.expired = enqueueSnackbar(messages.expired, { variant: 'certificateStatus', persist: true, }); } // 组件卸载时仅关闭当前组件打开的Snackbar return () => { if (snackbarKeys.current.expiring) { closeSnackbar(snackbarKeys.current.expiring); } if (snackbarKeys.current.expired) { closeSnackbar(snackbarKeys.current.expired); } }; }, [data, enqueueSnackbar, closeSnackbar]); return <div>Profile Statistics Content</div>; }
关键修改点说明
- 合并
useEffect逻辑:将两个独立的Snackbar处理逻辑合并为一个,监听完整的data对象,避免拆分依赖导致的逻辑冲突; - 精准控制Snackbar关闭:用
snackbarKeys保存每个Snackbar的唯一key,卸载时仅关闭当前组件打开的Snackbar,不会影响其他页面的Snackbar; - 调整挂载判断逻辑:
isFirstMount确保首次挂载(包括返回页面的重新挂载)时,等待数据加载完成后再触发Snackbar显示; - 避免重复显示:每次数据更新时先关闭之前的对应Snackbar,防止同一提示重复堆积。
注意事项
- 确保
userGetStatistics返回的data在组件重新挂载时能正确更新(若使用缓存,需保证返回最新状态); - 若
userGetStatistics是异步请求,首次挂载时data会从undefined变为有值,此时useEffect会自动触发,正确显示Snackbar。
内容的提问来源于stack exchange,提问作者Beibit Temirzhanov
相关产品推荐
相关产品推荐

