Notistack только в Redux без локального состояния? - PullRequest
0 голосов
/ 12 июня 2019

Я использую систему уведомлений 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,
        },
      }),
    );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...