Fortune Ikechi Fortune Ikechi is a frontend engineer based in Rivers State, Nigeria. He is a student of the University of Port Harcourt. He is passionate about community and software engineering processes.

How to create and send push notifications in React Native

8 min read 2265

React Native Push Notifications Using Expo

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 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

Push notifications in React Native APNs FCM

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):

The sample React Native app on an Android device

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:

Test notification with Expo on an Android device

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:


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.

A notification response on the GNU/Linux terminal

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.

A notification object on the GNU/Linux terminal

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 — .

Fortune Ikechi Fortune Ikechi is a frontend engineer based in Rivers State, Nigeria. He is a student of the University of Port Harcourt. He is passionate about community and software engineering processes.

6 Replies to “How to create and send push notifications in React…”

  1. 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.

  2. 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

  3. 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.

  4. Hello,

    I’m sorry to hear about this,
    will make sure to update this soon.

    thanks.

Leave a Reply