如何用React和Material UI创建通用连续Snackbars组件?
实现可复用的连续Snackbar通用组件(React 18 + MUI v5)
核心思路
通过React Context管理Snackbar队列,封装通用的Provider和自定义Hook,让应用内任意组件都能便捷触发连续Snackbar,无需重复编写队列逻辑。
1. 创建Snackbar上下文与Hook
新建SnackbarContext.jsx文件:
import { createContext, useContext, useState, useCallback } from 'react'; import { Snackbar, Alert } from '@mui/material'; const SnackbarContext = createContext(); export function SnackbarProvider({ children }) { const [snackbarQueue, setSnackbarQueue] = useState([]); // 关闭当前Snackbar,自动展示队列下一条 const handleClose = useCallback((event, reason) => { if (reason === 'clickaway') return; setSnackbarQueue(prev => prev.slice(1)); }, []); // 添加新提示到队列 const enqueueSnackbar = useCallback((message, options = {}) => { setSnackbarQueue(prev => [...prev, { id: Date.now(), message, severity: options.severity || 'info', autoHideDuration: options.autoHideDuration || 6000, ...options }]); }, []); return ( <SnackbarContext.Provider value={{ enqueueSnackbar }}> {children} {/* 仅渲染队列首项,关闭后自动切换下一条 */} {snackbarQueue.length > 0 && ( <Snackbar key={snackbarQueue[0].id} open={true} autoHideDuration={snackbarQueue[0].autoHideDuration} onClose={handleClose} anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }} > <Alert severity={snackbarQueue[0].severity} onClose={handleClose} variant="filled" sx={{ width: '100%' }} > {snackbarQueue[0].message} </Alert> </Snackbar> )} </SnackbarContext.Provider> ); } // 自定义Hook,简化组件调用 export function useSnackbar() { const context = useContext(SnackbarContext); if (!context) { throw new Error('useSnackbar必须在SnackbarProvider内部使用'); } return context; }
2. 在应用根组件注入Provider
修改App.jsx(或你的根组件文件):
import { SnackbarProvider } from './SnackbarContext'; import MainContent from './MainContent'; function App() { return ( <SnackbarProvider> <MainContent /> </SnackbarProvider> ); } export default App;
3. 在任意组件中复用调用
在需要触发提示的组件中,直接调用自定义Hook:
import { Button, Box } from '@mui/material'; import { useSnackbar } from './SnackbarContext'; function DemoComponent() { const { enqueueSnackbar } = useSnackbar(); const triggerMultipleSnackbars = () => { enqueueSnackbar('操作执行成功', { severity: 'success' }); enqueueSnackbar('请注意数据格式规范', { severity: 'warning', autoHideDuration: 8000 }); enqueueSnackbar('请求失败,请稍后重试', { severity: 'error' }); }; return ( <Box sx={{ p: 2 }}> <Button variant="contained" onClick={triggerMultipleSnackbars}> 触发多条提示 </Button> </Box> ); } export default DemoComponent;
关键说明
- 队列机制:新提示加入队列后仅渲染首项,关闭后自动切换下一条,实现连续展示
- 可扩展性:支持自定义提示类型、自动关闭时长等MUI原生属性
- 全局复用:通过Context实现状态共享,任意组件无需重复编写队列逻辑
内容的提问来源于stack exchange,提问作者ttous
相关产品推荐
相关产品推荐

