Skip to content

Instantly share code, notes, and snippets.

@srsajjad
Last active June 29, 2019 03:49
Show Gist options
  • Save srsajjad/870994f6424e72c774c83b807c76fd9d to your computer and use it in GitHub Desktop.
Save srsajjad/870994f6424e72c774c83b807c76fd9d to your computer and use it in GitHub Desktop.
// using snackbar with Redux
// create a feature component for Notification
// notification - action + container + reducer
// the action is exported
// so this can be dispatched from anywhere
// the container will be mounted inside the root component
// the root component will be wrapped with SnackbarProvider from notistack
// reducer
const defaultState = {
notifications: []
}
export let NotificationReducer = (state = defaultState, action) => {
switch (action.type) {
case 'ENQUEUE_SNACKBAR':
return {
...state,
notifications: [
...state.notifications,
{
...action.notification
}
]
}
case 'REMOVE_SNACKBAR':
return {
...state,
notifications: state.notifications.filter(
notification => notification.key !== action.key
)
}
default:
return state
}
}
// action
export const enqueueSnackbar = notification => ({
type: 'ENQUEUE_SNACKBAR',
notification: {
key: new Date().getTime() + Math.random(),
...notification
}
})
export const removeSnackbar = key => ({
type: 'REMOVE_SNACKBAR',
key
})
// container
import React, { Component } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { withSnackbar } from 'notistack'
import { removeSnackbar } from './NotificationAction'
class Notifier extends Component {
displayed = []
storeDisplayed = id => {
this.displayed = [...this.displayed, id]
}
shouldComponentUpdate ({ notifications: newSnacks = [] }) {
const { notifications: currentSnacks } = this.props
let notExists = false
for (let i = 0; i < newSnacks.length; i += 1) {
if (notExists) continue
notExists =
notExists ||
!currentSnacks.filter(({ key }) => newSnacks[i].key === key).length
}
return notExists
}
componentDidUpdate () {
const { notifications = [] } = this.props
notifications.forEach(notification => {
// Do nothing if snackbar is already displayed
if (this.displayed.includes(notification.key)) return
// Display snackbar using notistack
this.props.enqueueSnackbar(notification.message, notification.options)
// Keep track of snackbars that we've displayed
this.storeDisplayed(notification.key)
// Dispatch action to remove snackbar from redux store
this.props.removeSnackbar(notification.key)
})
}
render () {
return null
}
}
const mapStateToProps = state => ({
notifications: state.NotificationReducer.notifications
})
const mapDispatchToProps = dispatch =>
bindActionCreators({ removeSnackbar }, dispatch)
export default connect(
mapStateToProps,
mapDispatchToProps
)(withSnackbar(Notifier))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment