我正在使用 Material-ui Snackbar 创建我的 React 应用程序。
在我的项目中,我有很多组件,并且不想在每个组件中插入
类似:
从 'SnackbarUtils' 导入 showSnackbar;
showSnackbar('成功消息');
你必须以反应的方式来做。您可以通过创建高阶组件来实现这一点。
看看这个。 https://stackblitz.com/edit/snackbar-hoc?file=src/SnackbarHOC.js
将其扩展为Hook,然后调用一次即可使用带效果的状态来显示:
import { useSnackbar } from 'notistack';
import IconButton from "@mui/material/IconButton";
import CloseIcon from "@mui/material/SvgIcon/SvgIcon";
import React, {Fragment, useEffect, useState} from "react";
const useNotification = () => {
const [conf, setConf] = useState({});
const { enqueueSnackbar, closeSnackbar } = useSnackbar();
const action = key => (
<Fragment>
<IconButton onClick={() => { closeSnackbar(key) }}>
<CloseIcon />
</IconButton>
</Fragment>
);
useEffect(()=>{
if(conf?.msg){
let variant = 'info';
if(conf.variant){
variant = conf.variant;
}
enqueueSnackbar(conf.msg, {
variant: variant,
autoHideDuration: 5000,
action
});
}
},[conf]);
return [conf, setConf];
};
export default useNotification;
然后就可以使用它了:
const [msg, sendNotification] = useNotification();
sendNotification({msg: 'yourmessage', variant: 'error/info.....'})
这里是使用 Redux、Material-ui 和 MUI Snackbar 的完整工作示例的示例代码
import { random } from 'lodash'
import { Action } from 'redux'
import actionCreatorFactory, { isType } from 'typescript-fsa'
const actionCreator = actionCreatorFactory()
export type Notification = {
message: string
}
export type NotificationStore = Notification & {
messageId: number
}
export const sendNewNotification =
actionCreator<Notification>('NEW_NOTIFICATION')
const defaultState: NotificationStore = { message: '', messageId: 1 }
const reducer = (
state: NotificationStore = defaultState,
action: Action
): NotificationStore => {
if (isType(action, sendNewNotification)) {
const {
payload: { message }
} = action
return { message, messageId: random(0, 200000) }
}
return state
}
export default reducer
// useNotification to get state from Redux, you can include them into same file if you prefer
import { NotificationStore } from './notification'
export function useNotification(): NotificationStore {
return useSelector<NotificationStore>(
(state) => state.notification
)
}
// Notification React-component - Notification.tsx
import React, { useState } from 'react'
import Button from '@mui/material/Button'
import Snackbar from '@mui/material/Snackbar'
import IconButton from '@mui/material/IconButton'
import CloseIcon from '@mui/icons-material/Close'
type Props = {
message: string
}
export function Notification({ message }: Props): JSX.Element | null {
const [notiOpen, setNotiOpen] = useState(true)
if (!message) {
return null
}
return (
<Snackbar
anchorOrigin={{
vertical: 'bottom',
horizontal: 'left'
}}
open={notiOpen}
autoHideDuration={10000}
onClose={() => setNotiOpen(false)}
message={message}
action={
<React.Fragment>
<Button
color="secondary"
size="small"
onClick={() => setNotiOpen(false)}
>
Close
</Button>
<IconButton
size="small"
aria-label="close"
color="inherit"
onClick={() => setNotiOpen(false)}
>
<CloseIcon fontSize="small" />
</IconButton>
</React.Fragment>
}
/>
)
}
// Main App.tsx to run my application
import { Notification } from "./Notification.tsx"
import { useDispatch } from 'react-redux'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
const App: React.FC<AppProps> = () => {
const dispatch = useDispatch()
const { message, messageId } = useNotification()
return (
<ThemeProvider theme={appTheme}>
<Router>
<Switch>
<Route path="/public/:projectId" component={ProjectPage} />
<Route path="/login" component={LoginPage} />
<Route render={() => <PageNotFound />} />
</Switch>
</Router>
<Notification key={messageId} message={message} />
</ThemeProvider>
)
}
export default App
// Usage of hook in application - FileSomething.tsx
import { useDispatch } from 'react-redux'
import { useEffect } from 'react'
import { sendNewNotification } from 'src/redux/notification'
export function FileSomething(): JSX.Element {
function sendNotification() {
dispatch(
sendNewNotification({
message: 'Hey, im a notification'
})
)
}
useEffect(() => {
sendNotification()
}, [])
return (
<div>Component doing something</div>
)
}
我建议使用
notistack
- 它会为您处理状态,并且可以通过单个实例化跨组件使用:https://github.com/iamhosseindhv/notistack。
MUI 文档中也提到了:https://mui.com/material-ui/react-snackbar/#notistack。