Notistack: use closeSnackbar in SnackbarProvider

Created on 5 Feb 2019  路  14Comments  路  Source: iamhosseindhv/notistack

Is it possible to add the closeSnackbar function to the action of the Snackbar Provider so i don't have to do it for every individual instance?

For Example, I just tried the following,

return (
  <SnackbarProvider 
    autoHideDuration = {null}                                                                                                                            
    maxSnack = {3} 
    action = {[
      <IconButton key="close" color="inherit" onClick = {this.props.closeSnackbar(this)}><CloseIcon/></IconButton>
  ]}
  >
    <Login />
  </SnackbarProvider>
);


and i got an error saying that this.props.closeSnackbar is not a function.

Most helpful comment

@chapati23 useSnackbar can only be called inside body of a function component. So could great this action and pass it the action

const DismissAction = ({ id }) => {
    const { closeSnackbar } = useSnackbar()
    return (
        <Fragment>
            <Button onClick={() => alert(`Show more data for key: ${id}`)}>More</Button>
            <Button onClick={() => closeSnackbar(id)}>Close</Button>
        </Fragment>
    )
}

<SnackbarProvider
    action={key => <DismissAction id={key} />}
>
    <App />
</SnackbarProvider>

Worth mentioning you can't pass a prop called key, since it's reserved and handled differently by React. Here I've called it id.

All 14 comments

You can omit onClick part of the action and just pass the Icon button as an action. Default behaviour of action button is to dismiss/close the snackbar.

  <SnackbarProvider 
                                  maxSnack={3}
                                  anchorOrigin={{
                                    vertical: 'bottom',
                                    horizontal: 'right'
                                  }}
                                  action={(
                                    <Button>
                                      Close
                                    </Button>
                                  )}
                >
                  <App/>
</SnackbarProvider>

Sorry but I can't get the default behaviour.
Is there something wrong?

@dalborgo the answer above is for previous versions of notistack. In the latest version there is no default behaviour and you have to explicitly define an onClick event handler. Please refer to iamhosseindhv.com/notistack for example code. Let me know if you still had problems.

ok thanks. Can I ask you if there is a way to close the notistack with a "click away"?

You should be able to do something like this: @dalborgo

props.enqueueSnackbar('my mesage', {
     onClose: (event, reason, key) => {
          if (reason === 'clickaway') {
                this.props.closeSnackbar(key)
          }
     }
});

I think this should be re-opened, for me the default behavior also broke and I don't know how to get it back.

This no longer works:

<SnackbarProvider action={<Button>Dismiss</Button>}>

I also can't do this because useSnackbar only works within the provider of course:

const { closeSnackbar } = useSnackbar()
...
return (
  <SnackbarProvider action={<Button onClick={closeSnackbar}>Dismiss</Button>}>
  ...

What's the right way to get a default Dismiss button for all snackbars in the latest version?

@chapati23 useSnackbar can only be called inside body of a function component. So could great this action and pass it the action

const DismissAction = ({ id }) => {
    const { closeSnackbar } = useSnackbar()
    return (
        <Fragment>
            <Button onClick={() => alert(`Show more data for key: ${id}`)}>More</Button>
            <Button onClick={() => closeSnackbar(id)}>Close</Button>
        </Fragment>
    )
}

<SnackbarProvider
    action={key => <DismissAction id={key} />}
>
    <App />
</SnackbarProvider>

Worth mentioning you can't pass a prop called key, since it's reserved and handled differently by React. Here I've called it id.

Thank you @iamhosseindhv. Now I able to close the Snackbar globally. Have you any suggestions about the globally closing by "clickaway"?

Both this solutions don't work correctly (the reason is null):

props.enqueueSnackbar('my mesage', {
     onClose: (event, reason, key) => {
          if (reason === 'clickaway') {
                this.props.closeSnackbar(key)
          }
     }
});

// OR
<SnackbarProvider
    onClose={(event, reason, key) => {
          if (reason === 'clickaway') {
           this.props.closeSnackbar(key)
          }
     }}
>

I see. To be honest, I think the DX was better before when the default action was to dismiss the snackbar. Creating a wrapper component just to be able to use the hook feels a bit weird.

But nevertheless: your suggested approach works, thank you :)

@chapati23 I agree it is weird. It's just a compromise we had to make to allow multiple action for a snackbar.

@dalborgo atm I can't seem to come up with a solution. I'll post a solution as soon as I find one.

Another approach:

export const SnackbarDefaultAction = (key: OptionsObject["key"]) => {
  const Component = withSnackbar(({ closeSnackbar }) => {
    const onClick = () => closeSnackbar(key);

    return (
      <>
        <Button onClick={onClick}>Dismiss</Button>
      </>
    );
  });

  return <Component />;
};

Can't find solution without some buttons inside snackbar to close it with onclick..
should be an option to use all snackbars as clickable button\region,
smth. like that:
action={id => (onClick={closeSnackbar(id)}>
or just
onClick={closeSnackbar(id)}>

@TrejGun Assuming this is a class component:

```js
const providerRef = React.createRef()

ref={this.providerRef}
action={(id) => {

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kubalobo picture kubalobo  路  5Comments

njetsy picture njetsy  路  6Comments

FabianoLothor picture FabianoLothor  路  4Comments

usama-asfar picture usama-asfar  路  3Comments

alexisab picture alexisab  路  5Comments