Managing Notifications When an App Is Foregrounded or Backgrounded in React Native
Course: React Native Training
Topic: Managing Notifications When an App Is Foregrounded or Backgrounded
Course Link: React Native Training at JustAcademy
Demo Link: Register for a Course Demo
JustAcademy Website: Visit JustAcademy
1. Introduction to Notification Management
Notifications allow a mobile application to communicate important information to users, such as new messages, order updates, reminders, account activity, and system alerts. In React Native, notification behavior depends on whether the app is currently visible, running in the background, or completely closed.
Managing notifications correctly is important because the same notification may need different handling depending on the application's current state. For example, when a chat app is open, it may update the conversation screen without displaying a system notification. When the app is in the background, the operating system may display a notification that the user can tap to return to the conversation.
React Native developers commonly use Firebase Cloud Messaging (FCM), React Native Firebase, Expo Notifications, and platform-specific notification APIs to implement notification workflows. The appropriate implementation depends on the app's framework, platform, and notification requirements.
Learning Objectives
- Understand foreground, background, and quit application states.
- Learn the difference between local notifications and remote push notifications.
- Understand how Android and iOS handle incoming notifications.
- Handle messages when the app is active or running in the background.
- Respond to notification taps and navigate to the correct screen.
- Avoid duplicate notifications and repeated message processing.
- Test notification behavior across different app states.
2. Understanding Application States
A React Native app can occupy several lifecycle states. These states help determine whether notification content should update the current interface, appear in the notification tray, or trigger navigation when the user opens the app.
| Application State |
Description |
Typical Notification Behavior |
| Foreground |
The app is open and visible to the user. |
The app can update its interface or show an in-app notification. |
| Background |
The app is not currently visible but may still be running. |
The operating system may display a remote notification, depending on payload and platform behavior. |
| Quit or terminated |
The app process is not running. |
The operating system may display an eligible remote notification; tapping it may launch the app. |
| Inactive or transitional |
The app is temporarily transitioning between states or responding to system events. |
Notification display and event handling can vary by platform. |
2.1 Foreground State
When an application is in the foreground, the user is actively viewing it. A notification received during this state may not be presented as a standard system banner automatically, depending on the notification type, platform, and configuration.
Developers can respond by updating the screen, refreshing data, showing a banner inside the app, displaying a badge, or playing a sound when appropriate and permitted.
Example: If a user is reading a chat conversation and a new message arrives, the app can add the message directly to the conversation list instead of showing a duplicate notification.
2.2 Background State
When the user switches to another app or minimizes the current app, it usually enters the background. The operating system controls much of the notification presentation, particularly for remote notifications that include displayable notification content.
Background execution is restricted on both Android and iOS. Developers should not assume that JavaScript will always execute immediately or continuously while the app is backgrounded. Background handlers must follow the requirements of the notification library and the operating system.
2.3 Quit or Terminated State
A terminated app has no active application process. An eligible remote notification can still be presented by the operating system, but the app's JavaScript code may not run when the message first arrives. When the user taps the notification, the operating system may launch the app and provide information about the notification that opened it.
Cold-start notification handling is essential for deep linking. For example, tapping a notification about a new order should open the order details after the app initializes and the user is authenticated.
3. Types of Notifications in React Native
3.1 Local Notifications
Local notifications are scheduled or generated by the application on the device. They are useful for reminders, timers, task alerts, and scheduled events. They do not necessarily require a remote server when they are triggered.
Examples include:
- A reminder to complete a daily task.
- A calendar event alert.
- A scheduled medication or appointment reminder, where appropriate for the app's purpose.
- A countdown or locally scheduled activity notification.
3.2 Remote Push Notifications
Remote notifications are sent from a server or messaging platform to a device. Firebase Cloud Messaging is commonly used to deliver push messages across supported Android and Apple platform workflows.
Examples include:
- New chat messages.
- Order status updates.
- Account security alerts.
- Promotional messages where the user has appropriate choices and permissions.
- Updates from a subscribed service.
3.3 Notification Payload Types
| Payload Type |
Purpose |
Important Consideration |
| Notification payload |
Contains user-visible title and body information. |
The operating system can manage display in background scenarios. |
| Data payload |
Contains application-specific key-value data. |
Processing depends on app state, platform restrictions, and message configuration. |
| Combined payload |
Contains notification content and custom data. |
Avoid processing the same event twice when both system presentation and application handlers are involved. |
The exact delivery and execution behavior varies by operating system, message priority, payload format, permissions, and library configuration. Always validate the behavior on real devices.
4. Tools Used for Notification Handling
4.1 Firebase Cloud Messaging
Firebase Cloud Messaging (FCM) provides a way for a server or trusted backend to send messages to supported client applications. It can be used with React Native through a compatible notification integration.
Official documentation: Firebase Cloud Messaging Documentation
4.2 React Native Firebase Messaging
React Native Firebase provides a messaging module for handling messages and notification events. It supports foreground message listeners, background message handlers, and notification-open events when configured according to its documentation.
Documentation: React Native Firebase Messaging Usage
4.3 Expo Notifications
For Expo-based React Native projects, Expo Notifications provides APIs for notification permissions, foreground presentation behavior, notification response listeners, and other supported notification workflows.
Documentation: Expo Notifications API
Choose the library that matches the project architecture. Do not mix APIs from different notification libraries without understanding their setup requirements and event-handling differences.
5. Handling Notifications While the App Is in the Foreground
When a message arrives while the app is active, developers often want to update the interface immediately. For example, a messaging app can add a new message to its conversation, an e-commerce app can refresh an order status, or a collaboration app can update a notification counter.
5.1 Common Foreground Handling Strategies
- Update the interface: Add the new message to a list or refresh relevant data.
- Display an in-app banner: Show a small message within the application.
- Update unread counts: Increment or synchronize notification counters.
- Play a sound or provide haptic feedback: Only when appropriate and supported.
- Suppress redundant alerts: Avoid interrupting users who are already viewing the relevant content.
5.2 Example Using React Native Firebase
The following example listens for messages received while the app is active. It uses a simplified state update to demonstrate the pattern; a production app should use its existing state-management approach and handle duplicates.
import React, { useEffect, useState } from 'react';
import { View, Text } from 'react-native';
import messaging from '@react-native-firebase/messaging';
export default function NotificationScreen() {
const [latestMessage, setLatestMessage] = useState('');
useEffect(() => {
const unsubscribe = messaging().onMessage(async remoteMessage => {
const title = remoteMessage.notification?.title ?? 'New update';
const body = remoteMessage.notification?.body ?? '';
setLatestMessage(body ? `${title}: ${body}` : title);
});
return unsubscribe;
}, []);
return (
<View>
<Text>Foreground Notification</Text>
<Text>{latestMessage || 'No new messages'}</Text>
</View>
);
}
Explanation:
- The
useState hook stores the most recent message summary.
- The
useEffect hook registers a listener when the component mounts.
- The
messaging().onMessage() listener handles messages received in the foreground.
- The title and body are read safely because notification fields may be missing.
- The returned unsubscribe function removes the listener when the component unmounts.
This example updates text only. It does not automatically create a system banner or request notification permissions. If you want a visible in-app banner, implement one in the UI. If you want a system notification while the app is active, configure foreground presentation or use a suitable local-notification API, following the library's documentation.
6. Handling Notifications While the App Is in the Background
When the app is in the background, notification handling is different from foreground handling. For a displayable remote notification, the operating system may present the notification without requiring the React Native interface to be active.
6.1 Background Message Handler
With React Native Firebase, background messages can be handled by registering a background handler at the application entry point. The handler should be registered outside React components and should complete the required background work without relying on component state.
// index.js
import { AppRegistry } from 'react-native';
import messaging from '@react-native-firebase/messaging';
import App from './App';
import { name as appName } from './app.json';
messaging().setBackgroundMessageHandler(async remoteMessage => {
// Process the message using background-safe logic.
// For example, record an event or update supported local data.
console.log('Background message received:', remoteMessage.messageId);
});
AppRegistry.registerComponent(appName, () => App);
Important considerations:
- Register the handler at the application entry point, not inside a screen component.
- Keep background work short and focused.
- Do not assume the UI is mounted or available.
- Do not rely on indefinite JavaScript execution while the app is backgrounded.
- Follow platform-specific requirements for data-only messages, permissions, priority, and background execution.
- Avoid using this handler to display a second notification when the operating system already displays the same message.
6.2 Notification Display Versus Background Processing
Receiving a remote message and displaying a system notification are separate responsibilities. The operating system may display a notification payload while the app is in the background. A data-only message may require application processing, but execution is subject to operating system restrictions and delivery conditions.
For this reason, developers should decide whether each message is intended to be displayed by the operating system, processed silently by the app, or handled after the user opens the notification.
7. Handling Notifications When the App Is Terminated
When a user taps a notification while the app is closed, the app may start from a cold launch. The application needs to retrieve the notification that caused the launch and decide which screen should be displayed.
7.1 Initial Notification
React Native Firebase provides getInitialNotification() for retrieving the notification that opened the app from a quit state in supported scenarios.
import { useEffect } from 'react';
import messaging from '@react-native-firebase/messaging';
export function useInitialNotification() {
useEffect(() => {
const checkInitialNotification = async () => {
const remoteMessage =
await messaging().getInitialNotification();
if (remoteMessage) {
console.log(
'App opened from notification:',
remoteMessage.data
);
// Validate the data, then route after navigation is ready.
}
};
checkInitialNotification();
}, []);
}
In a production application, ensure the navigation container is ready before navigating. You may store the intended destination temporarily and process it once the app has completed initialization and any required authentication checks.
7.2 Notification Opened from the Background
When the app is already running in the background and the user taps a notification, a notification-open listener can process the event.
import { useEffect } from 'react';
import messaging from '@react-native-firebase/messaging';
export function useNotificationOpenHandler(onOpenNotification) {
useEffect(() => {
const unsubscribe =
messaging().onNotificationOpenedApp(remoteMessage => {
if (remoteMessage) {
onOpenNotification(remoteMessage.data);
}
});
return unsubscribe;
}, [onOpenNotification]);
}
The onOpenNotification callback should validate the incoming data and navigate to an appropriate screen only after navigation is ready. If the callback is recreated on every render, wrap it with useCallback or use a stable event-handling strategy to prevent unnecessary listener re-registration.
8. Managing Foreground Notification Presentation on iOS
On iOS, foreground notification presentation is governed by notification authorization, presentation settings, and the APIs used by the selected React Native library. A message can be received by the app without being presented as a system banner automatically.
When using React Native Firebase, developers can configure foreground presentation options using the relevant messaging API supported by their installed version and native setup. With Expo, foreground presentation behavior can be configured using Expo Notifications.
Expo example:
import * as Notifications from 'expo-notifications';
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowBanner: true,
shouldShowList: true,
shouldPlaySound: false,
shouldSetBadge: false,
}),
});
This example configures a foreground presentation policy in supported Expo SDK versions. Confirm the exact options supported by the version installed in your project. Foreground presentation settings do not replace the need to request authorization when required.
8.1 iOS Permissions
- Request notification authorization at an appropriate point in the user journey.
- Explain the value of notifications before prompting, where appropriate.
- Respect the user's decision if permission is denied.
- Do not assume that a device token means notification permission has been granted.
- Test banner, list, sound, and badge behavior on physical devices.
9. Managing Notifications on Android
Android notification behavior depends on the Android version, notification permission status, notification channel configuration, message payload, and application state.
9.1 Notification Channels
Android 8.0 and later require notification channels for notifications on the platform. Channels group notifications into categories such as messages, orders, reminders, or promotions. Users can manage channel preferences through system settings.
For example, a shopping application might use separate channels for order updates and marketing messages. Important transactional updates should not be hidden inside a low-priority promotional channel.
9.2 Android 13 and Later Permission
Android 13 (API level 33) introduced the runtime notification permission for many standard notification scenarios. Applications targeting the relevant API level should request notification permission where required and handle denial gracefully.
9.3 Foreground Service and Background Limits
Background execution restrictions mean an application cannot assume that it can run arbitrary tasks whenever a notification arrives. Foreground services are intended for specific ongoing user-visible work and have their own requirements; they should not be used merely to bypass notification restrictions.
Follow the Android platform documentation and the notification library's setup instructions for permissions, channels, message handling, and background behavior.
10. Requesting Notification Permissions
Notification permission handling should be part of the application's onboarding or feature flow. Request permission only when the user understands the benefit, and provide a useful fallback if permission is denied.
10.1 Example with React Native Firebase
import messaging from '@react-native-firebase/messaging';
export async function requestNotificationPermission() {
const authorizationStatus = await messaging().requestPermission();
const enabled =
authorizationStatus === messaging.AuthorizationStatus.AUTHORIZED ||
authorizationStatus === messaging.AuthorizationStatus.PROVISIONAL;
return enabled;
}
This example checks the authorization result exposed by React Native Firebase. Permission behavior differs between iOS and Android versions, so confirm the requirements for your app's target platforms and installed library version.
10.2 Permission Best Practices
- Explain why notifications are useful before requesting access.
- Do not repeatedly prompt users who have denied permission.
- Offer an in-app settings screen for notification preferences.
- Handle disabled notifications without crashing or blocking unrelated features.
- Keep server-side device-token registration and permission state synchronized where appropriate.
11. Navigating to a Screen from a Notification
Many notifications contain a destination, such as a chat conversation, order detail page, task, or article. A robust application should translate notification data into a safe navigation action.
11.1 Example Notification Data
{
"type": "order_update",
"orderId": "ORD-2048"
}
The app can inspect the type field and validate the orderId before navigating. Avoid blindly trusting arbitrary URLs or route names supplied in a push message.
11.2 Example Routing Logic
function getNotificationDestination(data) {
if (!data || typeof data !== 'object') {
return null;
}
if (data.type === 'order_update' && data.orderId) {
return {
screen: 'OrderDetails',
params: { orderId: String(data.orderId) },
};
}
if (data.type === 'chat_message' && data.conversationId) {
return {
screen: 'Conversation',
params: {
conversationId: String(data.conversationId),
},
};
}
return null;
}
This helper separates notification parsing from navigation. Your application can pass the returned destination to its navigation service after the navigation container is ready. Check authorization before exposing protected data.
12. Preventing Duplicate Notifications and Events
Duplicate notifications can occur when the operating system displays a notification and the application also creates a local notification for the same event. Duplicates may also arise when the app processes the same event through multiple listeners or retries.
12.1 Common Causes
- Displaying a local notification for a message that the operating system already presented.
- Registering multiple listeners without unsubscribing.
- Processing a message in both foreground and background logic without a clear event policy.
- Retrying server requests without idempotency controls.
- Displaying a notification each time a screen renders instead of when a new event is received.
12.2 Recommended Solutions
- Assign each event a stable message or event identifier.
- Track processed identifiers when appropriate.
- Register listeners once at a suitable application level.
- Clean up subscriptions when components unmount.
- Define a clear policy for which layer displays each notification.
- Keep server-side event processing idempotent.
13. Organizing Notification Logic in a React Native Project
Keeping notification logic separate from screen components improves maintainability and reduces the risk of duplicated listeners.
src/
notifications/
notificationPermissions.js
foregroundMessages.js
backgroundMessages.js
notificationNavigation.js
navigation/
AppNavigator.js
screens/
HomeScreen.js
OrderDetailsScreen.js
ConversationScreen.js
App.js
index.js
Suggested responsibilities:
notificationPermissions.js: permission requests and permission-state helpers.
foregroundMessages.js: foreground event subscriptions and UI updates.
backgroundMessages.js: background handler registration at the application entry point.
notificationNavigation.js: payload validation and destination selection.
AppNavigator.js: navigation routes and readiness management.
The exact file structure is flexible. The important principle is to keep registration, message processing, notification presentation, and navigation responsibilities clearly separated.
14. Testing Notifications Across App States
Notification testing should include different application states and different operating-system conditions. A successful test in the foreground does not guarantee correct background or terminated-state behavior.
| Test Case |
Expected Result |
| Receive message in foreground |
The app updates its UI or presents the configured in-app/system alert. |
| Receive displayable notification in background |
The operating system presents it when permitted and supported. |
| Tap notification from background |
The app opens or resumes and handles the notification data. |
| Tap notification from terminated state |
The app launches and processes the initial notification after initialization. |
| Notifications disabled |
The app handles the permission state gracefully and continues to support other features. |
| Malformed payload |
The app safely ignores or handles missing and invalid data. |
| Repeated event |
The same event does not create unintended duplicate UI entries or alerts. |
| Slow network or expired session |
The app handles data loading and authentication before displaying protected content. |
14.1 Real-Device Testing
Emulators and simulators are useful during development, but remote push notifications and background behavior can depend on device configuration and platform services. Test on real devices where possible, especially for permission prompts, token registration, background delivery, and notification interactions.
15. Troubleshooting Common Notification Problems
15.1 Notification Is Not Received
- Confirm the device has a valid registration token.
- Check Firebase project configuration and platform credentials.
- Confirm the server sends the message to the correct token or topic.
- Verify network connectivity, permissions, and device notification settings.
- Review the payload format and platform-specific delivery requirements.
15.2 Foreground Notification Is Not Visible
- Check whether the app's foreground listener is running.
- Remember that receiving a message does not always produce a system banner.
- Configure foreground presentation or create an in-app banner if needed.
- Verify that notification authorization and presentation settings allow the intended behavior.
15.3 Background Handler Does Not Run
- Confirm the background handler is registered at the application entry point.
- Check the installed library version and native configuration.
- Review message type, priority, platform limits, and payload format.
- Do not assume every data message will trigger immediate background execution.
- Test on a device with the expected app state and operating-system configuration.
15.4 Notification Opens the Wrong Screen
- Inspect the notification payload and destination fields.
- Wait until navigation is initialized before routing.
- Validate identifiers and route parameters.
- Handle authentication and unavailable content.
- Test both background-resume and cold-start notification flows.
15.5 Duplicate Alerts Appear
- Check whether both the operating system and application display the same message.
- Ensure listeners are not registered multiple times.
- Use event identifiers and idempotent processing.
- Review notification display logic across foreground and background paths.
16. Security and Privacy Best Practices
- Avoid placing passwords, access tokens, payment information, or other secrets in notification payloads.
- Keep sensitive notification previews generic when the device may be shared.
- Validate all payload data before using it for navigation or backend requests.
- Require authentication and authorization before showing protected records.
- Do not treat a device notification token as proof of user identity.
- Allow users to control relevant notification categories and preferences.
- Minimize the personal data included in logs and analytics.
- Use a trusted backend for sensitive operations rather than trusting client-side payloads.
17. Performance and Reliability Best Practices
- Keep background handlers short and avoid unnecessary network operations.
- Use pagination or targeted refreshes instead of reloading all application data.
- Clean up foreground listeners and notification response subscriptions.
- Handle missing payload fields safely.
- Make repeated event processing safe wherever possible.
- Provide loading, error, and retry states for notification-driven screens.
- Keep notification presentation consistent with the app's design system.
- Monitor delivery and interaction metrics without collecting unnecessary personal data.
18. Practical Project: Notification-Aware Order Tracking App
Project Objective: Build a React Native application that handles order notifications when the app is foregrounded, backgrounded, or launched from a terminated state.
Project Features
- Request notification permission at an appropriate point in the user journey.
- Register the device for supported remote messaging.
- Receive foreground messages and update the order screen.
- Display eligible background notifications through the operating system.
- Handle notification taps and route to order details.
- Validate the order identifier before fetching data.
- Handle unavailable orders, expired sessions, and network errors.
- Prevent duplicate events and redundant alerts.
Implementation Steps
- Create a React Native project and choose a compatible notification library.
- Complete the required native configuration and Firebase setup if using FCM.
- Implement permission handling and device registration.
- Register the foreground message listener.
- Register the background handler at the application entry point.
- Implement background-open and initial-notification handling.
- Build a validated notification-to-navigation mapping.
- Test foreground, background, terminated, denied-permission, and duplicate-event scenarios.
- Document platform-specific limitations and expected behavior.
Sample Test Payload
{
"notification": {
"title": "Order Update",
"body": "Your order status has changed."
},
"data": {
"type": "order_update",
"orderId": "ORD-2048"
}
}
This is an illustrative payload structure. The exact format required by your sending API and platform may differ. Send messages through a trusted backend or Firebase-supported tooling, and verify the payload format against current documentation.
19. Interview Questions and Answers
Q1. What is a foreground notification?
A foreground notification is a message received while the application is open and visible. The app may update its UI or show an in-app or configured system alert.
Q2. What is a background notification?
It is a notification received while the application is not visible. The operating system may present a displayable remote notification, while application processing depends on payload and platform conditions.
Q3. What is the difference between foreground and background message handling?
Foreground handling generally occurs while the app's JavaScript interface is active and can update the current screen. Background handling follows platform and library constraints and should not depend on a mounted UI.
Q4. What does messaging().onMessage() do?
It registers a listener for remote messages received while the app is in the foreground in React Native Firebase.
Q5. What is setBackgroundMessageHandler() used for?
It registers a handler for supported background messages. It should be registered at the application entry point and perform only appropriate background work.
Q6. What is the purpose of getInitialNotification()?
It retrieves notification information associated with opening the app from a quit state in supported React Native Firebase scenarios.
Q7. How can an app handle a notification tap while already in the background?
Use a notification-open event listener, validate the payload, and navigate after the navigation system is ready.
Q8. Why might a foreground notification not display a system banner?
Foreground system presentation is not automatic in every setup. The app may need to configure presentation behavior or show its own in-app notification.
Q9. Why are notifications duplicated?
Duplicates often occur when the operating system displays a notification and the app creates another one, or when multiple listeners process the same event.
Q10. Why is real-device testing important?
Notification delivery, permissions, background execution, and native configuration can vary by operating system and device settings, so real-device tests help verify actual behavior.
Q11. Should sensitive data be included in push notifications?
No. Keep payloads minimal, avoid secrets, validate incoming data, and fetch protected information securely after the user opens the app.
Q12. What should happen if notification permission is denied?
The app should continue to work where possible, respect the user's choice, and offer clear settings or alternative ways to access important information.
20. Quick Revision Checklist
- Understand foreground, background, and terminated states.
- Know the difference between local and remote notifications.
- Choose a notification library compatible with the project.
- Register foreground listeners and unsubscribe when appropriate.
- Register background handlers at the application entry point.
- Handle notification taps from both background and terminated states.
- Request permissions appropriately and respect user choices.
- Configure Android channels and iOS presentation behavior as needed.
- Validate notification payloads before navigation.
- Prevent duplicate alerts and repeated event processing.
- Test on physical devices and across different app states.
- Protect sensitive data and handle authentication before opening private content.
21. Conclusion
Managing notifications in React Native requires understanding how foreground, background, and terminated application states affect message delivery, display, and processing. Foreground messages are often used to update the active interface, background notifications may be presented by the operating system, and notification taps can launch or resume the app and guide users to relevant content.
A reliable implementation uses appropriate listeners, background handlers, permission management, payload validation, navigation readiness checks, and duplicate-event prevention. Because Android and iOS impose different notification and background-execution rules, always test the selected library and payload configuration on the target platforms.
22. Learning Resources