Repository navigation
fix: push tracking and handling issues - #13068
Conversation
Restores previous native behavior where notification tap tracking fired immediately when notifications arrived, not gated behind login/navigation state. This is important as the event is used as a session start event. Split the useEffect into two separate hooks: - First hook tracks notification taps immediately when pushNotification changes - Second hook handles navigation, still gated behind login/ready checks This prevents undertracking that was introduced during the notifee migration. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
| ...pushNotification.data, | ||
| }) | ||
| } | ||
| }, [pushNotification]) |
There was a problem hiding this comment.
the tracking event from the native side was sent every time the app opened from a push, and this event is important it is one of the special events that ladders up to sessions, this could account for some of the discrepancies with looker session tracking
|
|
||
| // Use requestAnimationFrame to ensure navigation happens after AuthenticatedRoutes | ||
| // has mounted and initialized (important when navigating after login) | ||
| requestAnimationFrame(() => { |
There was a problem hiding this comment.
when users log in we mount the AuthenticatedRoutes nav stack which results in navigation to the home tab at same time we try to handle the push navigation, home wins and push fails
There was a problem hiding this comment.
[not for this PR]: I know we like requestAnimationFrame, but what's the result of using InteractionManager.runAfterInteractions instead?
There was a problem hiding this comment.
can take a look!
| + // Reset listener count to allow proper re-initialization on bridge reload | ||
| + // This is necessary for modules that persist across bridge reloads (singletons, dev reload, Expo Updates) | ||
| + // Without this reset, startObserving will never be called again because _listenerCount > 1 | ||
| + _listenerCount = 0; |
There was a problem hiding this comment.
see the explanation in HACKS.md, not clear how often this happens in prod but if it does happen it could explain poor push performance because the native events to handle pushes will just silently fail with no tracking or navigation
|
|
||
| // Use requestAnimationFrame to ensure navigation happens after AuthenticatedRoutes | ||
| // has mounted and initialized (important when navigating after login) | ||
| requestAnimationFrame(() => { |
There was a problem hiding this comment.
[not for this PR]: I know we like requestAnimationFrame, but what's the result of using InteractionManager.runAfterInteractions instead?
MounirDhahri
left a comment
There was a problem hiding this comment.
Thanks for fixing this.
Sorry forgot to submit my review
* remove now unused analytics constant * fix: track push notification taps regardless of login state Restores previous native behavior where notification tap tracking fired immediately when notifications arrived, not gated behind login/navigation state. This is important as the event is used as a session start event. Split the useEffect into two separate hooks: - First hook tracks notification taps immediately when pushNotification changes - Second hook handles navigation, still gated behind login/ready checks This prevents undertracking that was introduced during the notifee migration. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * requestAnimationFrame when handling push to prevent initial nav interference * workaround for listenerCount being reset preventing observing starting * move event emitter fix to patch * update tests --------- Co-authored-by: Claude <noreply@anthropic.com>
Summary: If a subclass of RCTEventEmitter outlives the bridge and the bridge is invalidated, the invalidate method is called on RCTEventEmitter which calls stopObserving but does not change the listenerCount. Once the bridge is recreated and a listener added to the RCTEventEmitter if the listenerCount is > 1 startListening is never called: https://github.com/facebook/react-native/blob/a9a02689533f9cf30fc20cfc7be1ade4f4a624da/packages/react-native/React/Modules/RCTEventEmitter.m#L109 This just resets the listenerCount to prevent this. Probably not a good idea to have modules that outlive bridge in first place but this seems like unwanted behavior in any case :). ## Changelog: [iOS] [Fixed] - fix listenerCount not resetting for RCTEventEmitter Pull Request resolved: #54809 Test Plan: I tested this code via a patch in the artsy/eigen app repo: artsy/eigen#13068 The app was using a native module that posts events over the bridge to handle push notifications. Behavior before: 1. Start app listeners added to ARNotificationManager module, startListener called listenerCount = 2 2. Force a dev reload invalidating the bridge 3. Invalidate called on bridge and the native module causing stopObserving to be called but listenerCount remains 2 4. Bridge refreshes listeners added again but startObserving never called Behavior after: 1. Start app listeners added to ARNotificationManager module, startListener called listenerCount = 2 2. Force a dev reload invalidating the bridge 3. Invalidate called on bridge and the native module causing stopObserving to be called but listenerCount reset to 0 4. Bridge refreshes listeners added again listeners added again, startObserving called after first Reviewed By: cipolleschi Differential Revision: D88647586 Pulled By: javache fbshipit-source-id: 8a8b8b8cf4c7e683f02a08e40fc9d95c8ba4e4ac
This PR resolves DIAM-214
cc @artsy/diamond-devs
Description
Fixes a few issues with push and tracking related to push notifications:
before-login-low.mov
after-login-low.mov
before-event-emitter-low.mov
after-eventemitter-low.mov
Follow-ups
PR Checklist
To the reviewers 👀
Changelog updates
Changelog updates
Cross-platform user-facing changes
iOS user-facing changes
Android user-facing changes
Dev changes
Need help with something? Have a look at our docs, or get in touch with us.