Pablo
Pablo

Reputation: 2291

DeviceEventEmitter it's been listening twice

I don't know why when I fire an event the DeviceEventEmitter.addListener it's been emit once but listening twice.

I have a component Base that it's been add in every screen, something like

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

Where the ModalComponent should be able to open anytime that ModalVisible event it's fired.

  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>
    )
  }

And I have a Server the emits the event when needed

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

When Service.show it's called, the first log appears only once, but right away at the addListener it's been logged twice.

I've already tried

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

and

this.onModalVisible.bind(this)

But it gave me every the same problem.

Besides that, at the same moment the Modal it's been duplicated, where when I close, I have two modals to be close.

I also tried load all this in a new screen, without parents components, to see if that could be the problem, mas no. It still.

Upvotes: 5

Views: 10508

Answers (4)

muhsin Abbas
muhsin Abbas

Reputation: 1

_reactnative.deviceeventemitter.remotelistener is not a function in react native

  • when I upgrade the React Native version from 0.66 to 0.73, it mostly arises because most dependencies need to be upgraded individually inside the component where it is created. When I want to show it show then i upgrade some dependencies inside the component. Finally, the issue is solved.

Upvotes: 0

Muhammad Etisam Zafar
Muhammad Etisam Zafar

Reputation: 452

Wrap the "DeviceEventEmitter.addListener" with useEffect:

https://stackoverflow.com/a/73386913/7126848

Upvotes: 1

Lenoarod
Lenoarod

Reputation: 3620

today, I met the problem too. and I look at the source js. I find the DeviceEventEmit.addListener will actually call 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;
  }

in the inner method, it will push the listener's argus function into an array; when we call it many times, it will push many listeners' function.

so in the project, we have to avoid call it many times, and after the component unmount, we have to remove it.

Upvotes: 1

MaieonBrix
MaieonBrix

Reputation: 1624

I had the same problems with events being fired/registered twice with socket.io, my problem was due to the fact that I was adding eventListeners on DidMount method. But since my component was mounted multiple it was also adding eventListeners multiple times.

My guess is that you are using the same component multiple times and so adding multiple times the same eventListener. Try to add your eventsListener into another place that will be called only once.

Upvotes: 1

Related Questions