Last active
June 2, 2022 18:54
-
-
Save IlmariKu/2efeb230bf8643a1037ec428347fcd7d to your computer and use it in GitHub Desktop.
Notification-hook for React + Redux + Typescript + Material-UI Snackbar - 2022
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Global notification hook for React-applications. Easy way to send Notification for user in your application when needed | |
// Using: React + Redux + Typescript + Material-UI Snackbar | |
// Versions: | |
// Redux: 4.0.1 | |
// "@mui/material": "^5.4.1", | |
// "react": "^17.0.2", | |
// "react-router-dom": "^5.2.0", | |
// Redux Reducer, called notification.ts | |
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> | |
) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment