Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Problem with addEventListener removeEventListener #1610

Open
3 tasks done
serolgames opened this issue Dec 5, 2023 · 11 comments
Open
3 tasks done

[Bug]: Problem with addEventListener removeEventListener #1610

serolgames opened this issue Dec 5, 2023 · 11 comments

Comments

@serolgames
Copy link

serolgames commented Dec 5, 2023

What happened?

It seems that removeEventListener doesn't work as expected

I have the following code :

useEffect(() => 
{
    const eventMethod = (event: any) => 
    {
        console.log("Event listener called")
        let notification = event.getNotification();
        const data: any = notification.additionalData 

        if (data.refresh_messages == true) 
        {
            event.preventDefault();
        }
        else 
        {
            event.getNotification().display();
        }
    }

    OneSignal.Notifications.addEventListener('foregroundWillDisplay', eventMethod);

    return () => 
    {
        OneSignal.Notifications.removeEventListener('foregroundWillDisplay', eventMethod)
    };
}, []);

So when I'm on my page and I receive a notification my console says "Event listener called". When I leave the page I remove the event listener (with the return method of the useEffect) then when I receive a notification my console don't say "Event listener called". So... It's working ! But... no, because the notification is not shown. So in my opinion it seems that the removeEventListener does his work properly, but that the preventDefault() is still working because no notification with refresh_messages to true are displayed.

Steps to reproduce?

1. Install react native onesignal v5.0.3
2. Copy my code on another page (let's call it messagePage)
3. Go on your homePage and try to receive a notification (it will display)
4. Go on your messagePage and try to receive a notification (it won't display (as expected))
5. Go back to homePage and try to receive a notification (it won't display :( )

What did you expect to happen?

As I removed the listener. Then every notification should display

React Native OneSignal SDK version

5.0.3

Which platform(s) are affected?

  • iOS
  • Android

Relevant log output

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct
@Martinocom
Copy link

Are you using some libraries to navigate? Because for example react-navigation works better with useFocusEffect (instead of useEffect) when navigating and "focusing" on different screens.

@karlqueckfeldt
Copy link

karlqueckfeldt commented Feb 14, 2024

Did you find a solution to this? I'm using a combination of expo-router and the OneSignal Expo SDK, and the useFocusEffect for adding/removing the event listener. When I navigate from this route, the return statement in useFocusEffect is triggered properly, and the foregroundWillDisplay event is removed, but notifications still aren't shown again. What gives?

// route.tsx
  useFocusEffect(
    useCallback(() => {
      addForegroundWillDisplayListener();

      return () => {
        removeForegroundWillDisplayListener();
      };
    }, []),
  );

// PushNotificationsProvider.tsx
  const onForegroundWillDisplay = (event: NotificationWillDisplayEvent) => {
    event.preventDefault();
  };

  function addForegroundWillDisplayListener() {
    removeForegroundWillDisplayListener();
    OneSignal.Notifications.addEventListener(
      'foregroundWillDisplay',
      onForegroundWillDisplay,
    );
  }

  function removeForegroundWillDisplayListener() {
    OneSignal.Notifications.removeEventListener(
      'foregroundWillDisplay',
      onForegroundWillDisplay,
    );
  }

@serolgames
Copy link
Author

The problem is still here, event is removed but notifications don't show up again

@mathbalduino
Copy link

Same here

@mathbalduino
Copy link

mathbalduino commented Apr 25, 2024

Hello guys, I'm having similar issues. After I register a OneSignal.Notifications.addEventListener('foregroundWillDisplay', onNotificationArrived), I can't see my notifications anymore, even if I remove the listener. The only way to see them again, is to call notification.display(), inside the listener, again and again.

I don't know if it is happening on Android side. I'm working with iOS-only for now.

Let's take a look at my workaround:
(I'm using react-navigation, btw)

const SHOW_ALL_NOTIFICATIONS = (event: NotificationWillDisplayEvent) =>
  event.getNotification().display()

const YourPageComponent = () => {
  useFocusEffect(useCallback(() => {
    const onNotificationArrived = (event: NotificationWillDisplayEvent) => {
      const notification = event.getNotification()
      const data = notification.additionalData as (SomeDataType | undefined)
      const shouldPrevent = !!data && data.chat_id === chatID && data.SomeBooleanValue
      if (shouldPrevent) event.preventDefault()
      else notification.display()
    }
    OneSignal.Notifications.removeEventListener('foregroundWillDisplay', SHOW_ALL_NOTIFICATIONS)
    OneSignal.Notifications.addEventListener('foregroundWillDisplay', onNotificationArrived)
    return () => {
      OneSignal.Notifications.removeEventListener('foregroundWillDisplay', onNotificationArrived)
      OneSignal.Notifications.addEventListener('foregroundWillDisplay', SHOW_ALL_NOTIFICATIONS)
    }
  }, []))

  return <></>
}

Currently, on react-native-onesignal v5.1.2 with react-native v0.72.5, this is what's happening with me:

  • The listener is correctly added
  • After we call event.preventDefault() once, all subsequent notifications will behave like event.preventDefault() got called. The console logs will even print VERBOSE: OSNotificationWillDisplayEvent.preventDefault called for every notification
  • If we call notification.display(), it cancels the event.preventDefault() and the notification is displayed
  • The listener is correctly removed, the problem is not with the OneSignal.Notifications.removeEventListener() function. The listener is removed, the onNotificationArrived() function code is not executed, but the event.preventDefault() is still active

As you guys noted, we may have a flag, or something, that is not being unset. After we call event.preventDefault() we enable it, and it never gets disabled again. I was looking into the libs code and found this:
/ios/RCTOneSignal/RCTOneSignalEventEmitter.m:17

Apparently, after we call event.preventDefault(), we cache it. This affects, at least, two other functions:
/ios/RCTOneSignal/RCTOneSignalEventEmitter.m:292
/ios/RCTOneSignal/RCTOneSignalEventEmitter.m:464

I didn't have time to deep dive into it. The cache seems to be using the notification_id as the key, so it shouldn't be the problem for different notifications. But for some reason, all subsequent notifications print VERBOSE: OSNotificationWillDisplayEvent.preventDefault called on the console, so it may have something to do with the notification.preventDefault() function. Strange. The listener seems to be correctly removed, but if that's not the case, this may be the bug:
/ios/RCTOneSignal/RCTOneSignalEventEmitter.m:280

We can see that if there's an event registered, the preventDefault will be called before calling the event subscriber. I don't think that's the problem, since my listeners are being correctly removed and my workaround is based on that.

Well, hope I can help someone else. This workaround is working for me, even tho its ugly and not the ideal :/

@spyshower
Copy link

Any updates on this?

@mathbalduino
Copy link

Still happening

@ChristopherGabba
Copy link

This is still an issue. I can't get my listener to properly be removed either so its basically stacking listeners on each re-render

@twboc
Copy link

twboc commented Feb 4, 2025

Still reproducing this error with "react-native-onesignal": "^5.2.6"

Update: This is not reproduced in production builds. The reference to the listener is cleared properly when closing the app. Reload does not clean up this properly and new instances of listener function are not cleared since they have a different address in memory.
Line: 83
https://github.com/OneSignal/react-native-onesignal/blob/main/src/events/EventManager.ts

@twboc
Copy link

twboc commented Feb 4, 2025

It seems that the issue is cause by missing ios implementation for addNotificationClickListener and addNotificationForegroundLifecycleListener on lines 319 and 326 in file:

https://github.com/OneSignal/react-native-onesignal/blob/main/ios/RCTOneSignal/RCTOneSignalEventEmitter.m

I tested the same behaviour with addPermissionObserver and removePermissionObserver. I could reload the app many time and the event callback was triggered only once.

@nan-li
Copy link
Contributor

nan-li commented Feb 11, 2025

Hi everyone, I apologize for not getting eyes on this sooner. Thank you for the details. We will start by reproducing this behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants