【问题标题】:SnackBar displayed only the first time when dispatch an action mutiple times多次派发动作时,SnackBar 仅在第一次显示
【发布时间】:2019-09-17 21:24:13
【问题描述】:

我有一个snackBar,它根据调度的操作显示错误或成功消息。我尝试输入错误的用户凭据以对其进行测试并多次提交表单,但snackBar 仅在第一次出现。

SnackBar.tsx:

import { green } from "@material-ui/core/colors";
import IconButton from "@material-ui/core/IconButton";
import Snackbar from "@material-ui/core/Snackbar";
import SnackbarContent from "@material-ui/core/SnackbarContent";
import { makeStyles, Theme } from "@material-ui/core/styles";
import CheckCircleIcon from "@material-ui/icons/CheckCircle";
import CloseIcon from "@material-ui/icons/Close";
import ErrorIcon from "@material-ui/icons/Error";
import clsx from "clsx";
import React from "react";

const variantIcon = {
  error: ErrorIcon,
  success: CheckCircleIcon,
};

const useStyles1 = makeStyles((theme: Theme) => ({
  error: {
    backgroundColor: theme.palette.error.dark
  },
  icon: {
    fontSize: 20
  },
  iconVariant: {
    marginRight: theme.spacing(1),
    opacity: 0.9,
  },
  message: {
    alignItems: "center",
    display: "flex",
  },
  success: {
    backgroundColor: green[600]
  },
}));

export interface IProps {
  className?: string;
  message?: string;
  onClose?: () => void;
  variant: keyof typeof variantIcon;
}

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

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

interface IProps1 {
  open: boolean;
  handleClose: () => void;
  variant: any;
  message: string;
}
export default function CustomizedSnackbars(props: IProps1) {
  const { open, handleClose, variant, message } = props;
  return (
    <div>
      <Snackbar
        anchorOrigin={{
          horizontal: "left",
          vertical: "bottom",
        }}
        open={open}
        autoHideDuration={6000}
        onClose={handleClose}
      >
        <MySnackbarContentWrapper
          onClose={handleClose}
          variant={variant}
          message={message}
        />
      </Snackbar>
    </div>
  );
}

SignInContainer.tsx:

import React, { useEffect, useState } from "react";
import { connect } from "react-redux";
import SnackBar from "../../components/common/SnackBar";
import SignInForm from "./SignInForm";

interface IProps {
  message: string;
  variant: string;
}
const SingInContainer = (props: IProps) => {
  const { message, variant } = props;
  const [open, setSnackBarState] = useState(!!variant);

  useEffect(() => {
    setSnackBarState(!!variant);
  }, [variant]);

  const handleClose = () => {
    setSnackBarState(false);
  };

  return (
    <div>
      <SnackBar
        open={open}
        handleClose={() => {
          handleClose();
        }}
        variant={variant}
        message={message}
      />
      <SignInForm />
    </div>
  );
};

const mapStateToProps = (state: any) => {
  const { variant, message } = state.snackBar;

  return {
    message,
    variant,
  };
};

export default connect(mapStateToProps)(SingInContainer);

这段代码有什么问题,每次有消息要显示时如何显示小吃栏?

【问题讨论】:

  • 您的操作在哪里分派?
  • 您依赖 useEffect 打开 SnackBar - 只有在 variant 更改时才会再次调用它。由于您显示错误消息,我想大多数时候 variant 是相同的(因此在此组件的生命周期内不再有 useEffect 调用)

标签: reactjs typescript redux material-ui


【解决方案1】:

根据官方文档,我使用Effects with Cleanup 重置variant以更新snackBar消息。 SignInContainer.tsx:

import React, { useEffect, useState } from "react";
import { connect } from "react-redux";
import { resetAlert } from "../../actions/ui/snackBarActions";
import SnackBar from "../../components/common/SnackBar";
import SignUpForm from "./SignUpForm";

interface IProps {
  message: string;
  variant: string;
  resetAlert: () => void;
}
const SingUpContainer = (props: IProps) => {
  const { message, variant } = props;
  const [open, setSnackBarState] = useState(!!variant);

  useEffect(() => {
    setSnackBarState(!!variant);

    return function cleanUp() {
      resetAlert();
    };
  }, [variant]);

  const handleClose = () => {
    setSnackBarState(false);
  };

  return (
    <div>
      <SnackBar
        open={open}
        handleClose={() => {
          handleClose();
        }}
        variant={variant}
        message={message}
      />
      <SignUpForm />
    </div>
  );
};

const mapStateToProps = (state: any) => {
  const { variant, message } = state.snackBar;

  return {
    message,
    variant,
  };
};

export default connect(mapStateToProps, { resetAlert })(SingUpContainer);

【讨论】:

    猜你喜欢
    • 2015-11-14
    • 2017-10-11
    • 2013-09-25
    • 1970-01-01
    • 1970-01-01
    • 2017-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多