首页 > 解决方案 > StrictMode 导致 React 中的双重事件订阅

问题描述

我的 ReactJS 应用程序中有一个 EventEmitter,它具有调度和订阅功能,用于在我的站点内进行整体组件通信。React StrictMode 当然会导致我的视​​图重新渲染两次,包括它的构造函数。在 Home 视图中,我订阅了附加到相应回调的特定事件,因此在开发模式下,此事件被触发两次。这很烦人。

这是事件发射器:

export const EventEmitter = {
    events: {},
    dispatch(event, data) {
        if (!this.events[event]) return;
        this.events[event].forEach(callback => callback(data));
    },
    subscribe(event, callback) {
        if (!this.events[event]) this.events[event] = [];
        this.events[event].push(callback);
    }
}

我知道在生产中这不会发生,但是在我编码时发生这种情况令人沮丧。我应该怎么办?摆脱严格模式?

编辑:这就是我在主页视图中使用 EventEmitter 的方式:

import { EventEmitter } from '../../services/event-emitter';
import { Events } from '../../services/index';

class HomeView extends React.Component {

    constructor(props) {
        super(props);

        this.state = {
            items: []
        }

        EventEmitter.subscribe(Events.REMOVED_ITEM_EVENT, this.onItemRemoved);
    }

    ...
}

谢谢。

标签: reactjs

解决方案


当您订阅时constructor它调用了两次,尝试在组件的生命周期中订阅它应该完成的地方。

componentDidMount = () => {
  EventEmitter.subscribe(Events.REMOVED_ITEM_EVENT, this.onItemRemoved);
};

您甚至在文档中有这样的反模式示例:

class TopLevelRoute extends React.Component {
  constructor(props) {
    super(props);

    SharedApplicationState.recordEvent('ExampleComponent');
  }
}

乍一看,这段代码似乎没有问题。但是如果SharedApplicationState.recordEvent不是幂等的,那么多次实例化这个组件可能会导致无效的应用程序状态。这种微妙的错误可能不会在开发过程中显现出来,或者它可能会不一致而被忽视。


推荐阅读