Handling Notification Taps in expo-notifications: Launch vs. Runtime
This article is an English translation of the original Japanese article. When a user taps a push notification, the entry point differs depending on whether the app is running. If you only use one listener with Expo Router to navigate to the notification target screen, you may miss launches from the terminated state. In my app, I handle both cases with two separate mechanisms:…
When a user taps a push notification, the entry point varies based on whether the app is running or not. If only one listener is used with Expo Router to navigate to the notification target screen, launches from the terminated state may be missed. To handle both cases, the article describes two separate mechanisms: checking for the last notification response after launch and adding a notification response received listener when the app is running.
The notifications sent from the server include a destination path in data.url. Instead of parsing the displayed title or body to determine the destination, the article suggests passing a path the app can handle as separate data. This approach avoids parsing the displayed title or body to determine the destination.
When the app is in a terminated state, the article recommends checking for the last notification response after launch using Notifications.getLastNotificationResponseAsync(). This process is asynchronous, so it's advised to run it after authentication or when the Navigator is ready, to avoid navigation conflicts.
To handle notification taps while the app is running, addNotificationResponseReceivedListener() can be used to receive taps from either the background or foreground. To avoid duplicate listeners from screen remounts or Fast Refresh, the listener needs to be removed in the cleanup. The article shares a unified function, handleNotificationTap(), to validate notification data, extract the path, and navigate accordingly.
When implementing this solution, it's essential to unify both entry points while ensuring backward compatibility with previously sent notifications. The article recommends accepting both url and linkUrl, converting them to app-internal routes before passing, and defining allowed hosts and path formats to maintain safety.
The article also differentiates addNotificationReceivedListener and addNotificationResponseReceivedListener, explaining that the former is used when a notification is received, while the latter is used when a user taps the notification. The final example shows a unified hook, useNotificationNavigation(), that simplifies the process of handling notification taps based on the app's enabled state.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.