Last active
June 29, 2019 03:49
-
-
Save srsajjad/870994f6424e72c774c83b807c76fd9d to your computer and use it in GitHub Desktop.
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
// 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