To handle Firebase Cloud Messaging in React Native, install @react-native-firebase/messaging, configure iOS APNs certificates and Android notification channels, request notification permissions, retrieve the FCM token with getToken(), and set up foreground and background message handlers. Use onMessage for foreground notifications and setBackgroundMessageHandler for background delivery. On iOS, upload your APNs key in the Firebase Console for push notifications to work.
Implementing Firebase Cloud Messaging in React Native
Firebase Cloud Messaging (FCM) enables push notifications for React Native apps on both iOS and Android. This tutorial covers the full setup using the @react-native-firebase/messaging library, from installing native dependencies to handling messages in every app state: foreground, background, and quit. You will configure platform-specific requirements and build a complete notification handling flow.
Prerequisites
- A React Native project (0.72 or later) with @react-native-firebase/app configured
- A Firebase project with Cloud Messaging enabled
- For iOS: an Apple Developer account with APNs key uploaded to Firebase Console
- For Android: google-services.json added to android/app directory
Step-by-step guide
Install the messaging package
Install the messaging package
Add the @react-native-firebase/messaging package to your React Native project. This package provides the JavaScript API for FCM and the native modules for iOS and Android. After installing, run pod install for iOS to link the native dependencies. On Android, the native module is auto-linked.
1npm install @react-native-firebase/messaging23# For iOS:4cd ios && pod install && cd ..56# For Android: auto-linked, no additional stepsExpected result: The messaging package is installed and native dependencies are linked on both platforms.
Configure iOS APNs for push notifications
Configure iOS APNs for push notifications
iOS requires Apple Push Notification service (APNs) configuration for FCM to deliver notifications. Go to your Apple Developer account, create an APNs Authentication Key (p8 file) under Certificates, Identifiers & Profiles > Keys. Upload this key in Firebase Console > Project Settings > Cloud Messaging > Apple app configuration. In Xcode, enable Push Notifications and Background Modes (Remote notifications) capabilities for your app target.
1// In Xcode:2// 1. Select your target > Signing & Capabilities3// 2. Click + Capability > Push Notifications4// 3. Click + Capability > Background Modes > check 'Remote notifications'56// In Firebase Console:7// 1. Project Settings > Cloud Messaging8// 2. Under Apple app configuration, click Upload9// 3. Upload your APNs Authentication Key (.p8 file)10// 4. Enter the Key ID and Team ID from Apple Developer portalExpected result: Xcode shows Push Notifications and Remote notifications capabilities enabled. Firebase Console shows the APNs key uploaded.
Request notification permissions
Request notification permissions
On iOS, you must explicitly request permission from the user before showing notifications. On Android 13+, the POST_NOTIFICATIONS permission is also required. Call requestPermission() early in the app lifecycle, ideally during onboarding. Check the returned authorization status to determine if the user granted, denied, or has not decided.
1import messaging from '@react-native-firebase/messaging'23async function requestNotificationPermission() {4 const authStatus = await messaging().requestPermission()5 const enabled =6 authStatus === messaging.AuthorizationStatus.AUTHORIZED ||7 authStatus === messaging.AuthorizationStatus.PROVISIONAL89 if (enabled) {10 console.log('Notification permission granted:', authStatus)11 } else {12 console.log('Notification permission denied')13 }1415 return enabled16}Expected result: The permission dialog appears on iOS (and Android 13+), and the app receives the user's response.
Retrieve and manage the FCM token
Retrieve and manage the FCM token
The FCM token uniquely identifies this device for receiving push notifications. Retrieve it with getToken() and send it to your server to store alongside the user's account. Listen for token refreshes with onTokenRefresh() because tokens can change when the app is reinstalled or the user clears app data.
1import messaging from '@react-native-firebase/messaging'23async function getFCMToken() {4 const token = await messaging().getToken()5 console.log('FCM Token:', token)67 // Send token to your backend8 await saveTokenToServer(token)9 return token10}1112function listenForTokenRefresh() {13 return messaging().onTokenRefresh(async (newToken) => {14 console.log('Token refreshed:', newToken)15 await saveTokenToServer(newToken)16 })17}1819async function saveTokenToServer(token: string) {20 // Save to Firestore, your API, etc.21 // await firestore().collection('users').doc(userId).update({ fcmToken: token })22}Expected result: The FCM token is retrieved and stored on your server for sending targeted notifications.
Handle foreground messages
Handle foreground messages
When the app is in the foreground, FCM delivers messages silently without showing a notification banner. Use onMessage() to listen for incoming messages and display them yourself, either with a custom in-app banner or by creating a local notification using a library like notifee. The handler receives a RemoteMessage object with notification and data properties.
1import messaging from '@react-native-firebase/messaging'2import { useEffect } from 'react'34function useNotificationHandler() {5 useEffect(() => {6 const unsubscribe = messaging().onMessage(async (remoteMessage) => {7 console.log('Foreground message:', remoteMessage)89 // Option 1: Show in-app alert10 Alert.alert(11 remoteMessage.notification?.title || 'Notification',12 remoteMessage.notification?.body || ''13 )1415 // Option 2: Use notifee for a proper notification banner16 // await notifee.displayNotification({17 // title: remoteMessage.notification?.title,18 // body: remoteMessage.notification?.body,19 // })20 })2122 return unsubscribe23 }, [])24}Expected result: Foreground messages trigger the onMessage callback and can be displayed to the user.
Handle background and quit-state messages
Handle background and quit-state messages
For messages received when the app is in the background or has been quit, register a background handler using setBackgroundMessageHandler(). This must be called outside of any React component, typically in your index.js file. On Android, FCM automatically displays a notification from the notification payload. On iOS, the background handler runs as a headless JS task.
1// index.js (root of your React Native app)2import { AppRegistry } from 'react-native'3import messaging from '@react-native-firebase/messaging'4import App from './App'56// Register the background handler BEFORE AppRegistry.registerComponent7messaging().setBackgroundMessageHandler(async (remoteMessage) => {8 console.log('Background message:', remoteMessage)910 // Process the message (update badge, sync data, etc.)11 // Do NOT try to update UI state here12})1314AppRegistry.registerComponent('MyApp', () => App)Expected result: Background messages trigger the handler for data processing, and notification payloads automatically display a system notification.
Configure Android notification channels
Configure Android notification channels
Android 8.0+ requires notification channels for displaying notifications. Create a channel for your app's notifications with the appropriate importance level. Set the channel ID in your FCM message payload's android.notification.channel_id field to route notifications to the correct channel.
1import notifee, { AndroidImportance } from '@notifee/react-native'23async function createNotificationChannel() {4 await notifee.createChannel({5 id: 'default',6 name: 'Default Notifications',7 importance: AndroidImportance.HIGH,8 vibration: true,9 sound: 'default',10 })11}1213// Call this on app startup14createNotificationChannel()1516// When sending from server, include the channel:17// admin.messaging().send({18// token: userToken,19// notification: { title: 'Hello', body: 'World' },20// android: { notification: { channelId: 'default' } },21// })Expected result: Notifications appear with the correct importance level and sound on Android devices.
Complete working example
1import messaging, {2 FirebaseMessagingTypes,3} from '@react-native-firebase/messaging'4import { Alert, Platform } from 'react-native'56export async function requestPermission(): Promise<boolean> {7 const authStatus = await messaging().requestPermission()8 return (9 authStatus === messaging.AuthorizationStatus.AUTHORIZED ||10 authStatus === messaging.AuthorizationStatus.PROVISIONAL11 )12}1314export async function getToken(): Promise<string> {15 if (!messaging().isDeviceRegisteredForRemoteMessages) {16 await messaging().registerDeviceForRemoteMessages()17 }18 return messaging().getToken()19}2021export function onTokenRefresh(22 callback: (token: string) => void23): () => void {24 return messaging().onTokenRefresh(callback)25}2627export function onForegroundMessage(28 callback: (msg: FirebaseMessagingTypes.RemoteMessage) => void29): () => void {30 return messaging().onMessage(callback)31}3233export function setupForegroundAlert(): () => void {34 return messaging().onMessage(async (remoteMessage) => {35 Alert.alert(36 remoteMessage.notification?.title || 'New notification',37 remoteMessage.notification?.body || ''38 )39 })40}4142export async function initializeNotifications(): Promise<void> {43 const permitted = await requestPermission()44 if (!permitted) {45 console.warn('Notification permission denied')46 return47 }4849 const token = await getToken()50 console.log('FCM Token:', token)51 // TODO: Send token to your backend5253 onTokenRefresh((newToken) => {54 console.log('Token refreshed:', newToken)55 // TODO: Update token on backend56 })57}Common mistakes when handling Firebase Cloud Messaging in React Native
Why it's a problem: Not uploading the APNs key in Firebase Console, causing iOS notifications to silently fail
How to avoid: Go to Firebase Console > Project Settings > Cloud Messaging > Apple app configuration and upload your APNs Authentication Key (.p8 file) from Apple Developer portal.
Why it's a problem: Calling setBackgroundMessageHandler inside a React component instead of in index.js
How to avoid: Register the background handler at the top level of index.js, before AppRegistry.registerComponent. It must be available before any component mounts.
Why it's a problem: Not creating Android notification channels, causing notifications to be silently dropped on Android 8.0+
How to avoid: Create notification channels at app startup using notifee or the Android native API. Set the channel ID in your FCM payload.
Why it's a problem: Forgetting to enable Background Modes > Remote notifications in Xcode, preventing background delivery on iOS
How to avoid: In Xcode, select your target > Signing & Capabilities > add Background Modes and check 'Remote notifications'.
Best practices
- Request notification permissions during onboarding with context about why notifications are useful, not immediately on app launch
- Store FCM tokens in your database keyed by user ID and update them on every token refresh
- Use the @notifee/react-native library alongside FCM for rich foreground notification display
- Register setBackgroundMessageHandler in index.js before AppRegistry.registerComponent
- Create Android notification channels at app startup with the appropriate importance level
- Use APNs Authentication Keys instead of certificates for iOS, as keys do not expire
- Handle both notification payloads and data-only payloads to support all notification types
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I need to set up push notifications in my React Native app using Firebase Cloud Messaging. Show me the complete setup for both iOS and Android, including requesting permissions, getting the FCM token, and handling messages in foreground, background, and quit states.
Implement FCM push notifications in React Native with @react-native-firebase/messaging. Create a notifications utility module that requests permissions, retrieves and refreshes the FCM token, handles foreground messages with alerts, and registers a background message handler. Include iOS APNs and Android channel configuration.
Frequently asked questions
Why are my iOS notifications not arriving?
The most common cause is a missing APNs key in Firebase Console. Upload your p8 key under Project Settings > Cloud Messaging > Apple app configuration. Also verify Push Notifications and Background Modes capabilities are enabled in Xcode.
How do I send a notification to a specific user?
Store the user's FCM token in your database when they grant permission. On your server, use the Firebase Admin SDK's messaging().send() with the user's token to deliver a targeted notification.
What is the difference between notification and data messages?
Notification messages include a notification payload and are automatically displayed by the system when the app is in the background. Data messages contain only a data payload and are always delivered to your message handler, giving you full control over display.
Can I send notifications from the Firebase Console without writing server code?
Yes, go to Firebase Console > Messaging > Create your first campaign. You can target by topic, segment, or specific FCM tokens. This is useful for marketing notifications but not for transactional or user-triggered notifications.
How do I test push notifications on iOS Simulator?
The iOS Simulator supports push notification testing since Xcode 11.4. Create an APNs payload file and drag it onto the simulator. However, FCM-specific features like topics require a physical device.
Can RapidDev help implement push notifications for a React Native app?
Yes, RapidDev's engineering team can set up FCM for React Native including platform-specific configuration, server-side notification logic, and in-app notification handling.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation