Я использую систему уведомлений Notify
в моем приложении Reaction-Redux.Недавно я получил информацию о проблеме в моем коде.Этот код работает нормально, но мне сказали, что его можно упростить, сохраняя уведомления только в избыточном количестве.Я не очень хорошо понимаю это, поэтому я покажу весь код в этом посте.
Мне сообщили об этой проблеме: Я думаю, что уведомления должны храниться в Redux и только там, теперь они приходят с Redux и затем сохраняются в локальном состоянии.Это можно упростить.
Это мой Notifier.js component
, я должен импортировать его в контейнер, в котором я хочу отображать уведомления:
import { Component } from 'react';
import { makeNotificationsSelector } from 'containers/App/selectors';
import {
removeSnackbarAction,
closeSnackbarAction,
} from 'containers/App/actions';
import PropTypes from 'prop-types';
import { withSnackbar } from 'notistack';
import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import { compose } from 'redux';
class Notifier extends Component {
displayed = [];
storeDisplayed = id => {
this.displayed = [...this.displayed, id];
};
shouldComponentUpdate({ notifications, onCloseSnackbar, onRemoveSnackbar }) {
if (!notifications.length) {
this.displayed = [];
return false;
}
const { notifications: currentSnacks } = this.props;
let notExists = false;
for (let i = 0; i < notifications.length; i += 1) {
const newSnack = notifications[i];
if (newSnack.dismissed) {
onCloseSnackbar(newSnack.key);
onRemoveSnackbar(newSnack.key);
}
if (!notExists) {
notExists =
notExists ||
!currentSnacks.filter(({ key }) => newSnack.key === key).length;
}
}
return notExists;
}
componentDidUpdate({ onRemoveSnackbar }) {
const { notifications = [] } = this.props;
notifications.forEach(({ key, message, options = {} }) => {
if (this.displayed.includes(key)) return;
this.props.enqueueSnackbar(message, {
...options,
onClose: (event, reason, id) => {
if (options.onClose) {
options.onClose(event, reason, id);
}
onRemoveSnackbar(id);
},
});
this.storeDisplayed(key);
});
}
render() {
return null;
}
}
Notifier.propTypes = {
notifications: PropTypes.array,
enqueueSnackbar: PropTypes.func,
onRemoveSnackbar: PropTypes.func,
onCloseSnackbar: PropTypes.func,
};
const mapStateToProps = createStructuredSelector({
notifications: makeNotificationsSelector(),
});
function mapDispatchToProps(dispatch) {
return {
onRemoveSnackbar: key => dispatch(removeSnackbarAction(key)),
onCloseSnackbar: key => dispatch(closeSnackbarAction(key)),
};
}
const withConnect = connect(
mapStateToProps,
mapDispatchToProps,
);
export default compose(
withSnackbar,
withConnect,
)(Notifier);
Это мой Redux actions.js
:
import {
ENQUEUE_SNACKBAR,
CLOSE_SNACKBAR,
REMOVE_SNACKBAR,
} from './constants';
export function enqueueSnackbarAction(notification) {
const key = notification.options && notification.options.key;
return {
type: ENQUEUE_SNACKBAR,
notification: {
...notification,
key: key || new Date().getTime() + Math.random(),
},
};
}
export function closeSnackbarAction(key) {
return {
type: CLOSE_SNACKBAR,
dismissAll: !key,
key,
};
}
export function removeSnackbarAction(key) {
return {
type: REMOVE_SNACKBAR,
key,
};
}
Это мой Redux reducer.js
:
import produce from 'immer';
import {
ENQUEUE_SNACKBAR,
CLOSE_SNACKBAR,
REMOVE_SNACKBAR,
} from './constants';
export const initialState = {
notifications: [],
};
const loginPageReducer = (state = initialState, action) =>
produce(state, draft => {
switch (action.type) {
case ENQUEUE_SNACKBAR:
draft.notifications = [
...draft.notifications,
{
key: action.key,
...action.notification,
},
];
break;
case CLOSE_SNACKBAR:
draft.notifications = draft.notifications.map(notification =>
action.dismissAll || notification.key === action.key
? { ...notification, dismissed: true }
: { ...notification },
);
break;
case REMOVE_SNACKBAR:
draft.notifications = draft.notifications.filter(
notification => notification.key !== action.key,
);
break;
}
});
export default loginPageReducer;
... и я делаю уведомления с redux-saga
:
export function* makeNotification() {
yield put(
enqueueSnackbarAction({
message: 'Failed fetching data.',
options: {
key: new Date().getTime() + Math.random(),
variant: 'warning',
autoHideDuration: 3000,
},
}),
);
}