Reputation: 2291
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
Reputation: 1
_reactnative.deviceeventemitter.remotelistener is not a function in react native
Upvotes: 0
Reputation: 452
Wrap the "DeviceEventEmitter.addListener" with useEffect:
https://stackoverflow.com/a/73386913/7126848
Upvotes: 1
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
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