[unimodules][android][notifications] Event listener can miss `emit()` calls made soon after app launch
Problem
๐ Bug Report Summary of Issue If you call `Notifications.addResponseReceivedListener` in `useEffect` for example, the listener will not be triggered when opening an app from a completely killed state via a notification. This can also be demonstrated by adding a timeout to `componentDidMount` as shown here. Without 1 second timeout- events come through; with 1 second timeout- event's do not come through. I should note that the emit method is getting called in this case. Environment - output of `expo diagnostics` & the platform(s) you're targeting Reproducible Demo https://snack.expo.io/@charliecruzan/push-notifications Steps to Reproduce Need to run the app as a published experience or standalone app (or bare debug build) to see the behavior. Press "show notification" and kill the app, tap the notification, observe that response listener isn't triggered. Workaround The workaround (and possibly long-term solution) is to add the listener outside of any component, then it works as expected (presumably bc of how much sooner it's getting called?). I changed the docs to suggest this so fewer people run into this issue
Unverified for your environment
Select your OS to check compatibility.
1 Fix
Refactor Notification Listener Initialization
The issue arises because the event listener for notifications is being added within a React component's lifecycle method (e.g., useEffect or componentDidMount). When the app is launched from a killed state via a notification, the listener may not be registered in time to catch the emitted event, leading to missed notifications. By moving the listener registration outside of the component, it can be initialized sooner, ensuring it captures events as expected.
Awaiting Verification
Be the first to verify this fix
- 1
Move Listener Registration
Refactor your notification listener registration to occur outside of the React component. This ensures that the listener is set up immediately when the app starts, rather than waiting for the component to mount.
javascriptimport { Notifications } from 'expo-notifications'; // Register listener outside of component Notifications.addResponseReceivedListener(response => { console.log('Notification response:', response); }); - 2
Remove Component Lifecycle Dependency
Ensure that the listener is not tied to any component lifecycle methods. This prevents delays in listener registration that can occur if the component takes time to mount.
javascriptfunction App() { // Remove useEffect that adds listener return <YourComponent />; } - 3
Test Notification Handling
After implementing the changes, test the application by sending a notification and tapping it while the app is in a killed state. Confirm that the listener responds correctly.
- 4
Update Documentation
Update any relevant documentation to reflect the new listener registration method, ensuring that future developers are aware of this best practice.
Validation
To confirm the fix worked, run the app in a published state, send a notification, and tap it while the app is killed. Verify that the console logs the notification response correctly, indicating the listener was triggered.
Sign in to verify this fix
Environment
Submitted by
Alex Chen
2450 rep