Ad

Show SnackBar Material UI When Appear Erron In Mutation

I use Snack bar from Materia-UI page (first example - Customized SnackBars)

const variantIcon = {
  success: CheckCircleIcon,
  warning: WarningIcon,
  error: ErrorIcon,
  info: InfoIcon,
};

const styles1 = theme => ({
  success: {
    backgroundColor: green[600],
  },
  error: {
    backgroundColor: theme.palette.error.dark,
  },
  info: {
    backgroundColor: theme.palette.primary.dark,
  },
  warning: {
    backgroundColor: amber[700],
  },
  icon: {
    fontSize: 20,
  },
  iconVariant: {
    opacity: 0.9,
    marginRight: theme.spacing.unit,
  },
  message: {
    display: 'flex',
    alignItems: 'center',
  },
});

function MySnackbarContent(props) {
  const { classes, className, message, onClose, variant, ...other } = props;
  const Icon = variantIcon[variant];

  return (
    <SnackbarContent
      className={classNames(classes[variant], className)}
      aria-describedby="client-snackbar"
      message={
        <span id="client-snackbar" className={classes.message}>
          <Icon className={classNames(classes.icon, classes.iconVariant)} />
          {message}
        </span>
      }
      action={[
        <IconButton
          key="close"
          aria-label="Close"
          color="inherit"
          className={classes.close}
          onClick={onClose}
        >
          <CloseIcon className={classes.icon} />
        </IconButton>,
      ]}
      {...other}
    />
  );
}

MySnackbarContent.propTypes = {
  classes: PropTypes.object.isRequired,
  className: PropTypes.string,
  message: PropTypes.node,
  onClose: PropTypes.func,
  variant: PropTypes.oneOf(['success', 'warning', 'error', 'info']).isRequired,
};

const MySnackbarContentWrapper = withStyles(styles1)(MySnackbarContent);

const styles2 = theme => ({
  margin: {
    margin: theme.spacing.unit,
  },
});

class CustomizedSnackbar extends React.Component {
  state = {
    open: false,
  };

  handleClick = () => {
    this.setState({ open: true });
  };

  handleClose = (event, reason) => {
    if (reason === 'clickaway') {
      return;
    }
    this.setState({ open: false });
  };

  render() {
    return (
      <div>
        <Snackbar
          anchorOrigin={{
            vertical: 'bottom',
            horizontal: 'left',
          }}
          open={this.state.open}
          autoHideDuration={2000}
          onClose={this.handleClose}
        >
          <MySnackbarContentWrapper
            onClose={this.handleClose}
            variant="error"
            message="This is an error message!"
          />
        </Snackbar>
      </div>
    );
  }
}

export default withStyles(styles2)(CustomizedSnackbar);

In the example the snack bar is shown when click on button "OPEN SUCCESS SNACKBAR"

I would like to show the error snack bar when Mutation from Apollo on my Form gives an error.

render(){
 return(
  <div>
   <Mutation
    mutation={this.mutationQuery}
    onError={() =>
     //here show Snack Bar
    }
    onCompleted={data => { console.log(data); }}
   >
  {mutation => (
//here is the form
)}
)}

The problem is I dont know how to trigger to show the SnackBar in the on Error function. How to change state of Snack Bar? I was trying the solution from here, but I receive an error that

openSnackbarFn is not a function

Thanks in advance.

Ad

Answer

Fundamentally, you want your Snackbar to be a sibling of your Mutation, and let their common parent (i.e. your component) handle the Snackbar open/closed state.

Class-style component

class FormWithMutationAndSnackbar extends React.Component {
  state = {
    open: false
  }

  handleOpen = () => this.setState({ open: true })

  handleClose = () => this.setState({ open: false })

  render() {
    const { open } = this.state
    return(
      <React.Fragment>
        <Mutation
          mutation={this.mutationQuery}
          onError={(err) => {
            // use err to set Snackbar contents for example
            this.handleOpen()
          }
          onCompleted={data => { console.log(data); }}
        >
          {mutation => (
            //here is the form
          )}
        </Mutation>
        <Snackbar
          open={open}
          onClose={this.handleClose}
          // other Snackbar props
        >
          // Snackbar contents
        </Snackbar>
      </React.Fragment>
    )
  }
}

Functional component with Hooks

const FormWithMutationAndSnackbar = () => {
  const [open, setOpen] = useState(false)

  return(
    <React.Fragment>
      <Mutation
        mutation={this.mutationQuery}
        onError={(err) => {
          // use err to set Snackbar contents for example
          setOpen(true)
        }
        onCompleted={data => { console.log(data); }}
      >
        {mutation => (
          //here is the form
        )}
      </Mutation>
      <Snackbar
        open={open}
        onClose={() => setOpen(false)}
        // other Snackbar props
      >
        // Snackbar contents       
      </Snackbar>
    </React.Fragment>
  )
}
Ad
source: stackoverflow.com
Ad