Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save barbagrigia/308e057036aa190ad69ebc3abccf81a6 to your computer and use it in GitHub Desktop.
Save barbagrigia/308e057036aa190ad69ebc3abccf81a6 to your computer and use it in GitHub Desktop.
React / Redux / Semantic-UI toast notifications implementation
import _ from "lodash";
import {generateUUID} from "common/utils/UUID";
import {
NOTIFICATION_CLEAR,
NOTIFICATION_DISMISS,
NOTIFICATION_SHOW,
NotificationType,
} from "./notificationConstants";
export {NotificationType};
export function showNotification(options = {}) {
return (dispatch, getState) => {
const {message = ""} = options;
const {header = ""} = options;
const {type = NotificationType.INFO} = options;
const {id = generateUUID("notification")} = options;
const {dismissAfter = 5000} = options;
const showPayload = {message, header, type, id};
dispatch({type : NOTIFICATION_SHOW, payload : showPayload});
if(_.isNumber(dismissAfter)) {
setTimeout(() => {
dispatch(dismissNotification(id));
}, dismissAfter);
}
}
}
export function dismissNotification(id) {
return {
type : NOTIFICATION_DISMISS,
payload : {id}
};
}
export function clearAllNotifications() {
return {
type : NOTIFICATION_CLEAR,
};
}
export const NOTIFICATION_SHOW = "NOTIFICATION_SHOW";
export const NOTIFICATION_DISMISS = "NOTIFICATION_DISMISS";
export const NOTIFICATION_CLEAR = "NOTIFICATION_CLEAR";
export const NotificationType = {
SUCCESS : "SUCCESS",
INFO : "INFO",
WARNING : "WARNING",
ERROR : "ERROR",
}
import React, {Component} from "react";
import {connect} from "react-redux";
import _ from "lodash";
import { Message } from "semantic-ui-react";
import {Portal} from 'react-portal';
import {selectNotifications} from "./notificationSelectors";
import {dismissNotification} from "./notificationActions";
const mapState = (state) => ({
notifications : selectNotifications(state),
});
const NOTIFICATION_CONTAINER_STYLE = {
position : "fixed",
top : "10px",
right : 0,
left : 0,
zIndex : 1000,
width : "80%",
maxWidth : "400px",
margin : "auto",
};
const Notification = ({message, header, type, id, onCloseClick=_.noop}) => {
let headerText = header;
let messageText = message;
if(!headerText) {
headerText = message;
messageText = null;
}
const messageHeader = headerText ? <Message.Header>{headerText}</Message.Header> : null;
// Turn the type string into a boolean prop with the same name
const typeProp = type.toLowerCase();
const typeObj = { [typeProp] : true};
if(messageText) {
const messagePieces = messageText.split("\n");
messageText = messagePieces.map(piece => <div>{piece}</div>);
}
const onDismiss = () => onCloseClick(id);
return (
<Message {...typeObj} onDismiss={onDismiss} >
{messageHeader}
<Message.Content>{messageText}</Message.Content>
</Message>
);
}
const actions = {dismissNotification};
export class NotificationManager extends Component {
render() {
let {notifications = []} = this.props;
const renderedNotifications = notifications.map( notification => {
const {id} = notification;
return (
<Notification
key={id}
onCloseClick={this.props.dismissNotification}
{...notification}
/>
)
});
return (
<Portal isOpened={true} key="notificationsPortal">
<div style={NOTIFICATION_CONTAINER_STYLE}>
{renderedNotifications}
</div>
</Portal>
)
}
}
export default connect(mapState, actions)(NotificationManager);
import {createReducer} from "common/utils/utils";
import {
NOTIFICATION_CLEAR,
NOTIFICATION_DISMISS,
NOTIFICATION_SHOW,
} from "./notificationConstants";
const initialState = [];
function filterNotifications(notifications, id) {
return notifications.filter(notification => notification.id !== id);
}
export function showNotification(state, payload) {
const filteredNotifications = filterNotifications(state, payload.id);
return [payload, ...filteredNotifications];
}
export function dismissNotification(state, payload) {
return filterNotifications(state, payload.id);
}
export function clearNotifications(state, payload) {
return [];
}
export default createReducer(initialState, {
[NOTIFICATION_CLEAR] : clearNotifications,
[NOTIFICATION_DISMISS] : dismissNotification,
[NOTIFICATION_SHOW] : showNotification,
});
import {createSelector} from "reselect";
export const selectUI = state => state.ui;
export const selectNotifications = createSelector(
selectUI,
ui => ui.notifications,
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment