Editor’s note: This article was update on 10 June 2022 to include more up-to-date information on Expo, Firebase, and React Native, and reorganized for clarity.
Push notifications — messages from apps that are sent to users who have installed it — have become an important aspect to consider when building applications for businesses and users.
Push notifications are similar to SMS messages, but don’t cost anything to send. As a result, many businesses now prefer push notifications to send out information and alerts to users who have their apps installed. In this article, we’ll take a look at push notifications in React Native.
Contents
- What are push notifications?
- Push notification architecture in React Native
- Push notifications in React Native demo
- Getting a push notification token
- Sending a test notification
- Storing a push notification token in a project
- Sending notifications on the server
- Handling received notifications in React Native
What are push notifications?
Push notifications are messages or alerts sent by the makers of an application the user has installed. There are two main types of notifications, namely foreground and background notifications.
A foreground notification is a notification type that the user gets when the app is currently open and running, while background notifications are sent whether or not the app is currently open.
Push notifications are popular in the world of mobile app development for a number of reasons, including:
- Enabling firms to advertise products and offers at a reduced cost
- Improving overall user experience
- Sending of transaction receipts faster
- Converting more users
- They are reliable — users always get offline messages when they switch on their phones
Push notification architecture in React Native
When it comes to push notifications in React Native, there are several ways to set them up:
- Native platform-specific notification services (FCM/APNs)
- Expo push notifications service and other cloud services
- React Native libraries like react-native-push-notification
Native platform-specific notification services (FCM/APNs)
Both Android and iOS platforms offer native platform-specific APIs for receiving push notifications. Firebase Cloud Messaging (FCM) helps send push notifications for Android devices and the Apple Push Notification service (APNs) for iOS devices. We can use the React Native Firebase library to integrate FCM on Android and the push-notification-ios library to integrate APNs on iOS.
Also, the React Native Firebase library offers a way to receive push notifications on iOS through FCM. You can send remote notifications to registered mobile devices with firebase-admin and node-apn from a Node.js server.
Expo push notifications and other cloud services
Both FCM and APNs are platform-specific native push notification services, so we typically have to use different libraries in the app’s front end and back end if we directly use these native push notification services. Therefore, several cloud services offered ways to work with both FCM and APNs with unified source codes.
Popular push notification services are:
- Amazon Simple Notification Service (SNS)
- OneSignal
- Azure Notification Hubs
- Expo Push Notifications
These notification services provide an abstraction layer on top of native push notification systems with a managed intermediate push notification server (see the above diagram).
React Native libraries like react-native-push-notification
Libraries like react-native-push-notification and react-native-notifications offer native modules to receive remote notifications and show local notifications easily with a unified library API.
You can use either FCM/APNs directly or a managed push notification service with these libraries. We have to use the bare workflow in Expo to use these libraries because these are not included in the Expo app.
Push notifications in React Native demo
To use push notifications in a React Native application, first we need to register the app to get a push notification token. This token is a long string that uniquely identifies each device. Then, we’ll store the token in a database on the server, send a notification, and handle the received notifications we’ve sent.
Before we dive in too deep, we are going to add push notifications to a project that’s already developed. This project is an ecommerce React Native application for selling used items.
To download its source code into your computer, run the following command in your terminal:
git clone https://github.com/codezri/Done-With-It-App.git
Next, we’ll install the dependencies needed for the project and start the React Native development server:
yarn install yarn start
The above commands install dependencies and start the Expo development server, so you can test your application by using the Expo app on Android or iOS. The sample app looks like below with a working back end (we will set up the app backend after discussing the mobile frontend code):
Next, we’ll get a push notification token from React Native Expo to start receiving notifications to the app.
Getting a push notification token
To use push notifications in a React Native application, first we need to register the app to get a push notification token. Here, we will be using the notifications API in Expo.
To do this, let’s cd
into the navigation
directory and the AppNavigator
component. Here we are going to derive a token from Expo. Let’s get the Notifications
functions from Expo below:
import * as Notifications from 'expo-notifications';
The above functions help us request user permissions to send a push notification and receive a unique Expo notification token for the particular device.
Now, we will write an async function in the AppNavigator
component that will request a token from React Native Expo:
async function registerForPushNotificationsAsync() { let token; const { status: existingStatus } = await Notifications.getPermissionsAsync(); let finalStatus = existingStatus; if (existingStatus !== 'granted') { const { status } = await Notifications.requestPermissionsAsync(); finalStatus = status; } if (finalStatus !== 'granted') { alert('Failed to get push token for push notification!'); return; } token = (await Notifications.getExpoPushTokenAsync()).data; console.log(token); return token; }
In the code above, we are using the expo-notifications
module that we recently installed to get the user’s permission on notifications. The function waits to receive the notification permission status.
Next, we check to see if the permission is granted, and if it’s not, we display an alert about the error and return from the function immediately. If the token request process was successful, we return the token from the function. Besides, for now, we log the Expo token to the console for development purposes.
To call the above function for our application, we are going to use the useEffect
hook from React
:
const AppNavigator = () => { useEffect(() => { registerForPushNotificationsAsync(); }, []);
In the code above, we passed the useEffect
hook that we imported from re``act
and passed a function registerForPushNotificationsAsync
to make sure it’s only called once.
Now, open the application via the Expo app. Once you open the application, you can see the Expo push notification token on the console. When new users open the app, this unique token will be generated, so we can store these tokens in a server and send notifications to all registered devices programmatically. Save the token somewhere — we will use it soon to test notifications.
Sending a test notification
We can send test notifications to the device with the Expo notification tool by adding the push notification token. Go to the Expo notification tool, enter your token, enter a title and description, keep your app in the background, and click the Send a Notification button to send a test notification.
Now you can see the notification on your device, as shown in the following preview:
If you need to show notifications when your app is in foreground, you can add the following configuration to the AppNavigator.js
source file:
Notifications.setNotificationHandler({ handleNotification: async () => ({ shouldShowAlert: true }), }); const AppNavigator = () => { // ---- // ----
Now that we’ve tested Expo notifications manually, let’s store push notification tokens in a server and send notifications programmatically.
Storing a push notification token in a project
In order to store and use a push notification from our server, we need to configure our application user interface in a way that it is able to register new users and devices.
To achieve this, let’s go to our api
directory in our project and open a new file that we will call expoPushTokens.js
. Then do the following:
import client from './client'; const register = (pushToken) => client.post('/expoPushTokens', { token: pushToken }); export default { register, }
In the code above, we are first importing the client module, which is also in the api
directory.
We define a function register
that takes a pushToken
. Now, we’ll post a client or new user to the url
that’s on the backend /expoPushToken
. In the body of the request, we’re going to add an object token
that is set to pushToken
. Then, we’ll export as a default object with a register
method.
Next, we return to the AppNavigator
component, and, instead of logging our token on the console, we will send it to the server:
const AppNavigator = () => { useEffect(() => { registerForPushNotificationsAsync() .then(token => expoPushTokensApi.register(token)); }, []);
Now, we are sending the new user to get a token and the user info to our backend server. Later, we can use these tokens to send notifications to all registered devices.
More great articles from LogRocket:
- Don't miss a moment with The Replay, a curated newsletter from LogRocket
- Learn how LogRocket's Galileo cuts through the noise to proactively resolve issues in your app
- Use React's useEffect to optimize your application's performance
- Switch between multiple versions of Node
- Discover how to animate your React app with AnimXYZ
- Explore Tauri, a new framework for building binaries
- Advisory boards aren’t just for executives. Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sending notifications on the server
To send push notifications to the server, we need to use one of the SDKs provided by Expo. If you visit the documentation, it provides us with information on how to implement push notifications on the server in many languages.
In this tutorial, I’ll be working with a Node.js server. Here is a link to the server source code I’ve used for this tutorial. We’ll visit the utilities
directory in the server and include the Expo
SDK on it. To do this, we first do the following:
git clone https://github.com/iamfortune/DoneWithIt-Backend.git
cd
into the newly cloned Git repository. Next we install the npm
packages using the command:
npm install
Next, add your computer’s local network IP address to the React Native app’s baseURL
and backend project’s assetsBaseUrl
.
Then we start our development server with:
npm start
You can see some pre-included listings in the React Native app if you keep both computer and mobile device on the same network.
Now, go to the pushNotifications.js
file and add the Expo
SDK to the packages:
npm i expo-server-sdk const { Expo } = require("expo-server-sdk");
Next, we’ll write a function that will receive our push notifications — both the push tokens and the message we want to send the user. Then, we’ll create a new chunk method to handle the push notifications:
const sendPushNotification = async (targetExpoPushToken, message) => { const expo = new Expo(); const chunks = expo.chunkPushNotifications([ { to: targetExpoPushToken, sound: "default", body: message } ]);
Now you can call the sendPushNotification
function anywhere in the server code to send notifications to any device based on the Expo push notification token, as shown below:
const { Expo } = require('expo-server-sdk'); const sendPushNotification = require('../utilities/pushNotifications'); // ---- // ---- if (Expo.isExpoPushToken(expoPushToken)) { await sendPushNotification(expoPushToken, message); } // ----
You can check an example usage of the sendPushNotification
function in the routes/messages.js
file. Next, let’s determine how to handle notifications we’ve received in the React Native app.
Handling received notifications in React Native
To handle received notifications, first we need to have an event listener that will be called every time the user taps on a notification.
Let’s add an event listener inside of our AppNavigator
function that takes in the notification object:
const AppNavigator = () => { const responseListener = useRef(); useEffect(() => { registerForPushNotificationsAsync() .then(token => expoPushTokensApi.register(token)); // Works when app is foregrounded, backgrounded, or killed responseListener.current = Notifications.addNotificationResponseReceivedListener(response => { console.log('--- notification tapped ---'); console.log(response); console.log('------'); }); // Unsubscribe from events return () => { Notifications.removeNotificationSubscription(responseListener.current); }; }, []); // ---- // ----
Once you send test notifications via the Expo push notification tool and tap on incoming notifications, you will see notification tap responses on the console, as follows.
The Expo notifications package offers a listener to detect incoming notification events if the application is foregrounded. The following code snippet logs a particular notification object once your foregrounded app receives a notification via the Expo push notifications system:
// ---- // ---- Notifications.setNotificationHandler({ handleNotification: async () => ({ shouldShowAlert: true }), }); const AppNavigator = () => { const notificationListener = useRef(); useEffect(() => { registerForPushNotificationsAsync() .then(token => expoPushTokensApi.register(token)); notificationListener.current = Notifications.addNotificationReceivedListener(notification => { console.log('--- notification received ---'); console.log(notification); console.log('------'); }); // Unsubscribe from events return () => { Notifications.removeNotificationSubscription(notificationListener.current); }; }, []); // ---- // ----
The above code logs notification objects if your application is in foreground. Look at the following preview.
You can browse the complete source code of this React Native application from this GitHub repository. Also, you can browse the complete server-side code from this GitHub repository.
Note that here I received notifications to my Android device without setting up FCM because I was using the Expo app for development. If you need to test your app without the Expo app or you wish to deploy your app to Google Play or Apple App Store, make sure to generate FCM and APNs credentials properly. The official Expo documentation can guide you in setting up FCM and APNs for production apps.
You can develop and test your applications without FCM/APNs configurations, thanks to the Expo app.
Conclusion
In this article, we’ve seen why push notifications are popular and here to stay in the application world, and we’ve learned how to send push notifications in React Native applications by adding notification tokens, sending them from the server, and displaying them on user devices with the Expo notification APIs.
LogRocket: Instantly recreate issues in your React Native apps.

LogRocket is a React Native monitoring solution that helps you reproduce issues instantly, prioritize bugs, and understand performance in your React Native apps.
LogRocket also helps you increase conversion rates and product usage by showing you exactly how users are interacting with your app. LogRocket's product analytics features surface the reasons why users don't complete a particular flow or don't adopt a new feature.
Start proactively monitoring your React Native apps — try LogRocket for free.
Good Article 👍
Thank you
Glad you like it!
Probably this article applies to bare React native project and not to actual “expo start” project? I lost the connection when I reached “To do this, let’s cd into the Navigation directory and the AppNavigator”. I am using expo to develop my first react native project. I wish there was some mention regarding this in this article.
Hi,
I followed your post for my school homework but then soon got stuck because the modules and commands in here are outdated. It would be very much appreciated for a code update please.
Currently expo updates with new modules below and the commands and syntax changed a lot :
import * as Notifications from ‘expo-notifications’;
import * as Permissions from ‘expo-permissions’;
Thanks in advanced
One more interesting thing is installing expo-notifications posed a lot of internal errors for module missing files. For which I updated expo to version 40, delete node_modules and all lock files (yarn.lock and package-json.lock), then npm install. But could not solve it.
Lemme know if you observe the same or else. Thanks.
Hello,
I’m sorry to hear about this,
will make sure to update this soon.
thanks.