Reactjs 如何防止键控事件冒泡进入MUI Snackbar?

Reactjs 如何防止键控事件冒泡进入MUI Snackbar?,reactjs,material-ui,Reactjs,Material Ui,我们已经创建了一个通知系统,它使用带有操作按钮和关闭按钮的MaterialUI Snackbar。我为enter添加了一个侦听器事件,以便特定通知的操作将触发并关闭Snackbar。我遇到的问题是,在执行此操作之后,chrome的默认行为仍然有触发通知的按钮。如果按enter键,它不仅会触发通知,还会触发通知中的操作按钮。有没有关于如何防止这种情况的建议 import React from 'react'; import { connect } from 'react-redux'; impor

我们已经创建了一个通知系统,它使用带有操作按钮和关闭按钮的MaterialUI Snackbar。我为
enter
添加了一个侦听器事件,以便特定通知的操作将触发并关闭Snackbar。我遇到的问题是,在执行此操作之后,chrome的默认行为仍然有触发通知的按钮。如果按enter键,它不仅会触发通知,还会触发通知中的操作按钮。有没有关于如何防止这种情况的建议

import React from 'react';
import { connect } from 'react-redux';
import { withStyles } from '@material-ui/core/styles';
import IconButton from '@material-ui/core/IconButton';
import DeleteIcon from '@material-ui/icons/Delete';
import Tooltip from '@material-ui/core/Tooltip';
import { NotifierConfirm, enqueueInfo } from '@paragon/notification-tools';
import { deleteDocument } from '../../actions/documents';
import { getSelectedDocument } from '../../selectors/documents';
import { jobIsLocked } from '../../modules/jobLocking'; // eslint-disable-line

const styles = ({
  border: {
    borderRadius: 0,
  },
});

class DeleteDocument extends React.Component {
  state = {
    deleteDocumentOpen: false,
  }

  onDeleteFile = () => {
    if (jobIsLocked()) {
      return;
    }

    this.setState({ deleteDocumentOpen: true });
  }

  closeDeleteDocument = () => {
    this.setState({ deleteDocumentOpen: false });
  };

  onConfirmDelete = () => {
    this.props.onDeleteFile(this.props.selectedDocument.id);
    this.setState({ deleteDocumentOpen: false });
  }

  render() {
    const { classes } = this.props;
    return (
      <div>
        <Tooltip disableFocusListener id="delete-tooltip" title="Delete Document">
          <div>
            <IconButton
              className={`${classes.border} deleteDocumentButton`}
              disabled={(this.props.selectedDocument == null)}
              onClick={this.onDeleteFile}
            >
              <DeleteIcon />
            </IconButton>
          </div>
        </Tooltip>
        <NotifierConfirm
          open={this.state.deleteDocumentOpen}
          onClose={this.closeDeleteDocument}
          onClick={this.onConfirmDelete}
          message="Are you sure you want to DELETE this document?"
          buttonText="Delete"
        />
      </div>
    );
  }
}

const mapStateToProps = (state) => {
  const selectedDocument = getSelectedDocument(state);

  return {
    selectedDocument,
  };
};

function mapDispatchToProps(dispatch) {
  return {
    onDeleteFile: (documentId) => {
      dispatch(deleteDocument(documentId));
    },
    enqueueInfo,
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(DeleteDocument));
从“React”导入React;
从'react redux'导入{connect};
从“@material ui/core/styles”导入{withStyles}”;
从“@material ui/core/IconButton”导入IconButton;
从“@material ui/icons/Delete”导入DeleteIcon;
从“@material ui/core/Tooltip”导入工具提示;
从“@paragon/notification tools”导入{NotifierConfirm,enqueueInfo};
从“../../actions/documents”导入{deleteDocument};
从“../../selectors/documents”导入{getSelectedDocument};
从“../../modules/jobLocking”;/”导入{jobIsLocked}eslint禁用线
常量样式=({
边界:{
边界半径:0,
},
});
类DeleteDocument扩展了React.Component{
状态={
deleteDocumentOpen:false,
}
onDeleteFile=()=>{
if(jobIsLocked()){
返回;
}
this.setState({deleteDocumentOpen:true});
}
closeDeleteDocument=()=>{
this.setState({deleteDocumentOpen:false});
};
OnConfigrmDelete=()=>{
this.props.ondelettefile(this.props.selectedDocument.id);
this.setState({deleteDocumentOpen:false});
}
render(){
const{classes}=this.props;
返回(
);
}
}
常量mapStateToProps=(状态)=>{
const selectedDocument=getSelectedDocument(状态);
返回{
选定的文档,
};
};
功能图DispatchToprops(调度){
返回{
onDeleteFile:(documentId)=>{
发送(删除文件(文档ID));
},
排队信息,
};
}
导出默认连接(mapStateToProps、mapDispatchToProps)(使用样式(样式)(删除文档));

从“React”导入React;
从'@material ui/core/styles'导入{withStyles,withStyles,StyleRulesCallback};
从“@material ui/core/Button”导入按钮;
从“@material ui/core/Snackbar”导入Snackbar;
从“@material ui/core/IconButton”导入IconButton;
从“@material ui/icons/Close”导入CloseIcon;
从“@material ui/core/RootRef”导入RootRef;
接口通知confirmProps{
开放:布尔;
onClose:任何;
onClick:()=>void;
消息:字符串;
messageSecondary?:任何;
buttonText:字符串;
}
键入OwnProps=NotifierConfirmProps&WithStyles;
常量样式:StyleRulesCallback=()=>({
小吃条:{
玛金托普:85,
zIndex:10000000,
“&div:第一个孩子”:{
“&div:第一个孩子”:{
宽度:“100%”,
},
},
},
关闭:{
填充:8,
边缘左:8,
},
按钮颜色:{
背景颜色:“#F3D06E”,
},
messageDiv:{
宽度:“100%”,
}
});
类NotifierConfigComponent扩展了React.Component{
notifierRef:React.reObject;
构造器(道具:OwnProps){
超级(道具);
//创建一个ref来存储textInput DOM元素
this.notifierRef=React.createRef();
this.focusNotifier=this.focusNotifier.bind(this);
}
按键处理程序=(事件:任意)=>{
如果(!this.props.open)返回;
如果(event.keyCode===27){
this.props.onClose();
}
如果(event.keyCode===13){
this.props.onClick();
}
}
focusNotifier(){
//使用原始domapi显式聚焦文本输入
//注意:我们正在访问“current”以获取DOM节点
//this.notifierRef.current.focus();这将不起作用
}
componentDidMount(){
document.addEventListener('keyup',this.keyPressHandler,false);
}
组件将卸载(){
document.removeEventListener('keyup',this.keyPressHandler,false);
}
render(){
const{classes}=this.props;
返回(
);
}
}
导出const NotifierConfirm=with样式(样式)(NotifierConfirmComponent);

在回调中,您应该调用
Event.preventDefault()
Event.stopPropagation()
,值得注意的是,这两者并不相同。这里是文档:,

这适用于初始按键,但我确实希望在通知打开后,
enter
键“单击”操作按钮。它要么一路冒泡,要么在打开通知时停止。
import React from 'react';
import { withStyles, WithStyles, StyleRulesCallback } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import Snackbar from '@material-ui/core/Snackbar';
import IconButton from '@material-ui/core/IconButton';
import CloseIcon from '@material-ui/icons/Close';
import RootRef from '@material-ui/core/RootRef';

interface NotifierConfirmProps {
  open: boolean;
  onClose: any;
  onClick: () => void;
  message: string;
  messageSecondary?: any;
  buttonText: string;
}

type OwnProps = NotifierConfirmProps & WithStyles<typeof styles>;

const styles: StyleRulesCallback = () => ({
  snackbar: {
    marginTop: 85,
    zIndex: 10000000,
    '& div:first-child': {
      '& div:first-child': {
        width: '100%',
      },
    },
  },
  close: {
    padding: 8,
    marginLeft: 8,
  },
  buttonColor: {
    backgroundColor: '#F3D06E',
  },
  messageDiv: {
    width: '100%',
  }
});

class NotifierConfirmComponent extends React.Component<OwnProps> {
  notifierRef: React.RefObject<{}>;
  constructor(props: OwnProps) {
    super(props);
    // create a ref to store the textInput DOM element
    this.notifierRef = React.createRef();
    this.focusNotifier = this.focusNotifier.bind(this);
  }
  keyPressHandler = (event: any) => {
    if (!this.props.open) return;
    if (event.keyCode === 27) {
      this.props.onClose();
    }
    if (event.keyCode === 13) {
      this.props.onClick();
    }
  }

  focusNotifier() {
    // Explicitly focus the text input using the raw DOM API
    // Note: we're accessing "current" to get the DOM node
    // this.notifierRef.current.focus();  this will not work
  }

  componentDidMount() {
    document.addEventListener('keyup', this.keyPressHandler, false);
  }

  componentWillUnmount() {
    document.removeEventListener('keyup', this.keyPressHandler, false);
  }

  render() {
    const { classes } = this.props;
    return (
      <React.Fragment>
        <RootRef rootRef={this.notifierRef}>
          <Snackbar
            className={classes.snackbar}
            anchorOrigin={{
              vertical: 'top',
              horizontal: 'center',
            }}
            open={this.props.open}
            onClose={this.props.onClose}
            ContentProps={{
              'aria-describedby': 'message-id',
            }}
            message={
              <div className={classes.messageDiv} id="message-id">
                {this.props.message}<br />
                {this.props.messageSecondary}
              </div>}
            action={[
              <Button
                className={`${classes.buttonColor} confirmActionButton`}
                variant="contained"
                key={this.props.buttonText}
                size="small"
                onClick={this.props.onClick}
              >
                {this.props.buttonText}
              </Button>,
              <IconButton
                key="close"
                aria-label="Close"
                color="inherit"
                className={classes.close}
                onClick={this.props.onClose}
              >
                <CloseIcon />
              </IconButton>,
            ]}
          />
        </RootRef>
      </React.Fragment>
    );
  }
}

export const NotifierConfirm = withStyles(styles)(NotifierConfirmComponent);