DeviceEventEmitter一直在听两次

时间:2017-11-22 13:54:04

标签: react-native

我不知道为什么当我触发一个事件时 DeviceEventEmitter.addListener 它已经发出一次但是听了两次。

我有一个 Base 组件,它已经在每个屏幕上添加,例如

<View>
    {this.props.children}
    <ModalComponent />
</View>

ModalComponent 应该能够在 ModalVisible 事件的任何时候打开它。

  constructor (props) {
    super(props)
    this.state = {
      modalVisible: false
    }
  }

  componentDidMount() {
    DeviceEventEmitter.addListener('ModalVisible', this.onModalVisible)
  }

  componentWillUnmount () {
    DeviceEventEmitter.removeListener('ModalVisible', this.onModalVisible)
  }

  onModalVisible = (args) => {
    console.log(['ModalVisible', args]) // logging twice
    this.setState({
      modalVisible: args.visible
    })
  }

  close () {
    this.setState({
      modalVisible: false
    })
  }

  onRequestClose = () => {
    this.close()
  }

  render() {
    return (
      <Modal animationType={'slide'} transparent={false} visible={this.state.modalVisible} onRequestClose={this.onRequestClose}>
        ...
      </Modal>
    )
  }

我有一台服务器,在需要时发出事件

  static show (data) {
    console.log(['Service.show', data]) // only once
    DeviceEventEmitter.emit('ModalVisible', { visible: true })
  }

当Service.show被调用时,第一个日志只出现一次,但是立即出现在 addListener ,它被记录了两次。

我已经尝试了

this.listener = DeviceEventEmitter.addListener(...)
this.listener.remove()

this.onModalVisible.bind(this)

但它给了我同样的问题。

除此之外,在同一时刻,模态已被复制,当我关闭时,我有两个模态要接近。

我也尝试在没有父组件的情况下在新屏幕中加载所有这些,以查看是否可能出现问题,mas no。它仍然。

2 个答案:

答案 0 :(得分:1)

今天,我也遇到了这个问题。我看一下源代码js。我发现DeviceEventEmit.addListener实际上会调用EventSubscriptionVendor.addSubscription method

_subscriber: EventSubscriptionVendor;
addListener(
    eventType: string,
    listener: Function,
    context: ?Object,
  ): EmitterSubscription {
    return (this._subscriber.addSubscription(
      eventType,
      new EmitterSubscription(this, this._subscriber, listener, context),
    ): any);
  }

 addSubscription(
    eventType: string,
    subscription: EventSubscription,
  ): EventSubscription {
    invariant(
      subscription.subscriber === this,
      'The subscriber of the subscription is incorrectly set.',
    );
    if (!this._subscriptionsForType[eventType]) {
      this._subscriptionsForType[eventType] = [];
    }
    const key = this._subscriptionsForType[eventType].length;
//here is the point
this._subscriptionsForType[eventType].push(subscription);
    subscription.eventType = eventType;
    subscription.key = key;
    return subscription;
  }

在内部方法中,

会将侦听器的argus函数推入数组;当我们多次调用它时,它将推动许多侦听器的功能。

因此在项目中,我们必须避免多次调用它,并且在卸载组件之后,必须将其删除。

答案 1 :(得分:0)

我在使用socket.io触发/注册两次事件时遇到了同样的问题,我的问题是因为我在DidMount方法上添加了eventListeners。但是由于我的组件已经多次安装,因此它还多次添加了eventListeners。

我的猜测是你多次使用相同的组件,因此多次添加相同的eventListener。尝试将eventsListener添加到另一个只调用一次的地方。