You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React无状态组件中Office UI Fabric Panel的OnDismiss事件触发两次

解决你的onDismiss函数触发两次问题

嘿,我瞅了你的代码,发现几个可能导致这个问题的点,咱们一个个说:

最可能的原因:重复绑定/重复传递事件属性

首先看你CurrentProjects组件里渲染PopUpPanel的这段代码:

const popUpPanelProps:IPopUpPanelProps = {
  project: project,
  showPanel: this.state.showPanel,
  //onDismiss: this.onDismiss
};

return (
  <div className={styles.currentProjects}>
    {element}
    <PopUpPanel {...popUpPanelProps} onDismiss={this.onDismiss} />
  </div>
);

虽然你注释了popUpPanelProps里的onDismiss,但如果之前没注释的时候,相当于给PopUpPanel传了两次onDismiss属性——不过JSX里后面的属性会覆盖前面的,所以这个可能不是当前的核心问题,但还是建议统一传递方式,要么都放popUpPanelProps里,要么单独写,别混着来避免混淆。

更关键的是看你的PopUpPanel组件(虽然你只贴了开头):如果在这个组件里,你给Office UI Fabric的Panel组件重复绑定了onDismiss事件,比如同时绑定到自定义关闭按钮和面板自带的onDismiss属性上,那点击关闭图标时就会触发两次。比如错误的写法:

// 错误示例!别这么写
const PopUpPanel = (props) => {
  return (
    <Panel
      isOpen={props.showPanel}
      onDismiss={props.onDismiss}
    >
      {/* 多余的自定义关闭按钮,又绑定了一次onDismiss */}
      <button onClick={props.onDismiss}>关闭</button>
    </Panel>
  );
};

这种情况下,点击Panel自带的关闭图标,会触发Panel的onDismiss,同时如果事件冒泡到内部按钮,就会导致函数执行两次。

另一个可能:React Strict Mode的锅

如果你是在开发环境遇到这个问题,那大概率是React Strict Mode搞的鬼。Strict Mode在开发环境下会刻意让某些函数(比如setState的更新函数、组件的render方法)执行两次,目的是帮你发现代码里的副作用问题。你的onDismiss里用了函数式setState:

private onDismiss():void{
  this.setState((prevState:ICurrentProjectsState)=> {
    return { showPanel: false };
  });
}

这个更新函数会被执行两次,但这只是开发环境的检查,生产环境不会有这个情况。你可以去项目入口文件里看看有没有<React.StrictMode>标签,去掉它试试,应该就不会触发两次了(不过不建议长期关闭,Strict Mode能帮你提前踩坑)。

解决方案

  1. 检查PopUpPanel的代码:确保你只给Office UI Fabric的Panel组件绑定一次onDismiss={props.onDismiss},没有在其他地方(比如自定义关闭按钮、遮罩层)重复绑定这个函数。正确的写法应该是这样:
import * as React from 'react';
import { Panel, PanelType } from 'office-ui-fabric-react';
import IPopUpPanelProps from "./IPopUpPanelProps";

const PopUpPanel: React.FC<IPopUpPanelProps> = (props) => {
  return (
    <Panel
      isOpen={props.showPanel}
      onDismiss={props.onDismiss}
      type={PanelType.smallFixedFar}
      // 其他必要属性
    >
      {/* 你的面板内容 */}
      <h1>{props.project?.Title}</h1>
    </Panel>
  );
};

export default PopUpPanel;
  1. 统一属性传递方式:在CurrentProjects里,把onDismiss统一放进popUpPanelProps里,避免混淆:
// 推荐写法:统一放进props对象里
const popUpPanelProps:IPopUpPanelProps = {
  project: project,
  showPanel: this.state.showPanel,
  onDismiss: this.onDismiss
};

return (
  <div className={styles.currentProjects}>
    {element}
    <PopUpPanel {...popUpPanelProps} />
  </div>
);
  1. 验证Strict Mode的影响:如果是开发环境的问题,去掉入口文件里的<React.StrictMode>标签,看看是否解决问题。如果解决了,那就是Strict Mode的正常行为,不用慌,生产环境会正常。

总结

最可能的原因就是重复绑定了onDismiss事件,先检查你的PopUpPanel组件代码,确保只绑定一次。如果是开发环境的问题,那大概率是Strict Mode的原因,不用在意,生产环境会正常。

内容的提问来源于stack exchange,提问作者Shashank

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:56:24