Notistack: Action no longer Working

Created on 24 May 2019  ·  3Comments  ·  Source: iamhosseindhv/notistack


In the new version, the action flag no longer seems to be closing. You can see this on your own demo site.

In reviewing the site, the Custom Snackbar seems to be working as intended.

Expected Behavior

I expect when I click on GOT IT, it would close the snackbar.

Current Behavior

When I click the GOT IT, it does not close the snackbar and it remains "forever".

Steps to Reproduce


Link: https://iamhosseindhv.com/notistack#persist-snackbar

  1. Click on the persist button
  2. Click GOT IT
  3. See that it is not removed.
  4. Spam the persist button.
  5. Click the normal button

Context

I am currently using this code in my own app, and it no longer closed. Checked your site to see if it was happening there as well. Which it seems to be. I cleared the cache and did a force reload and the error seemed to persist. This is happening on all browsers.

Your Environment

| Tech | Version |
|------------|---------|
| Notistack | v0.8.5 |
| React | v16.8.6 |
| Browser | Chrome: 74.0.3729.169 |
| Material-UI | v3.9.3 |

Most helpful comment

I did this by creating a component and a function...

You can do this with less code, but I wanted it to be clear what was going on

Component file (Named: CloseIcon/index.js):

import React from 'react';
import PropTypes from 'prop-types';
import { useSnackbar } from 'notistack';

import withStyles from '@material-ui/styles/withStyles';
import IconButton from '@material-ui/core/IconButton';

import CloseIcon from '@material-ui/icons/Close';

const styles = {
  icon: {
    position: '20px',
  },
};

function CloseSnackbar({ classes, key }) {
  const { closeSnackbar } = useSnackbar();

  return (
    <IconButton
      aria-label="Close"
      color="inherit"
      onClick={() => {
        closeSnackbar(key);
      }}
    >
      <CloseIcon className={classes.icon} />
    </IconButton>
  );
}

CloseSnackbar.propTypes = {
  classes: PropTypes.object.isRequired /* From withStyles */,
  key: PropTypes.string.isRequired,
};

export default withStyles(styles)(CloseSnackbar);

Note: If you are not using hooks, the you'd do the injectSnackbar and closeSnackbar, and remove useSnackbar, like you would.

Function (Used to inject component into action):

import React from 'react';

import CloseSnackbar from './index'; /* The above component */

const injectClose = key => <CloseSnackbar key={key} />;

export default injectClose;

Provider:

<SnackbarProvider
   maxSnack={3}
   preventDuplicate
   action={injectClose} /* The above function */
   anchorOrigin={{
   vertical: 'bottom',
   horizontal: 'right',
  }}>…</SnackbarProvider>

This works around not having the provider instance around that you probably see happening in the console. By injecting it this way the instance exists.

All 3 comments

@ksavery
You have to manually close the snackbar on onClick event of action button. Previously, the default behaviour was to close the snackbar so you didn't have to provide a onClick event. Documentation website is now fixed as well.

this.props.enqueueSnackbar('Your notification here', {
                variant: 'error',
                persist: true,
                action: key => (
                    <Button
                        style={{ color: 'white' }}
                        size="small"
                        onClick={() => this.props.closeSnackbar(key)}
                    >Got it
                    </Button>
                ),
})

Hey @iamhosseindhv

And how do you do when you provide action props at SnackbarProvider ?

I did this by creating a component and a function...

You can do this with less code, but I wanted it to be clear what was going on

Component file (Named: CloseIcon/index.js):

import React from 'react';
import PropTypes from 'prop-types';
import { useSnackbar } from 'notistack';

import withStyles from '@material-ui/styles/withStyles';
import IconButton from '@material-ui/core/IconButton';

import CloseIcon from '@material-ui/icons/Close';

const styles = {
  icon: {
    position: '20px',
  },
};

function CloseSnackbar({ classes, key }) {
  const { closeSnackbar } = useSnackbar();

  return (
    <IconButton
      aria-label="Close"
      color="inherit"
      onClick={() => {
        closeSnackbar(key);
      }}
    >
      <CloseIcon className={classes.icon} />
    </IconButton>
  );
}

CloseSnackbar.propTypes = {
  classes: PropTypes.object.isRequired /* From withStyles */,
  key: PropTypes.string.isRequired,
};

export default withStyles(styles)(CloseSnackbar);

Note: If you are not using hooks, the you'd do the injectSnackbar and closeSnackbar, and remove useSnackbar, like you would.

Function (Used to inject component into action):

import React from 'react';

import CloseSnackbar from './index'; /* The above component */

const injectClose = key => <CloseSnackbar key={key} />;

export default injectClose;

Provider:

<SnackbarProvider
   maxSnack={3}
   preventDuplicate
   action={injectClose} /* The above function */
   anchorOrigin={{
   vertical: 'bottom',
   horizontal: 'right',
  }}>…</SnackbarProvider>

This works around not having the provider instance around that you probably see happening in the console. By injecting it this way the instance exists.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

VincentLanglet picture VincentLanglet  ·  3Comments

iamhosseindhv picture iamhosseindhv  ·  7Comments

usama-asfar picture usama-asfar  ·  3Comments

FabianoLothor picture FabianoLothor  ·  4Comments

seannguyn picture seannguyn  ·  4Comments