Apple Push Notifications with React Native and Node.js
By: Ross Bulat
Tags: Mobile App Development, Programming, React Native, JavaScript, Software Engineering

Implementing APNs within React Native

With provisioning complete, we’ve now arrived at the React Native side. React Native is responsible for a couple of things for setting up APNs:

Pulling up the Request Permission dialogue at a particular point in the app to give the user an opportunity to accept or reject Push Notifications. After which the user will have to delve into their Settings to enable notifications, if they initially reject them.

at a particular point in the app to give the user an opportunity to accept or reject Push Notifications. After which the user will have to delve into their Settings to enable notifications, if they initially reject them. Registering a device token, and providing it to us in plain text in Javascript so we can use it when sending notifications.

A device token is a unique identifier for a particular device that APNs are enabled for, and will only be presented if Push Notifications are indeed enabled for the app.

To integrate these features we’ll be utilising two packages, that streamline the process into easy-to-use APIs:

react-native-push-notification : A simple wrapper for React Native that provides both Local and Remote Notifications support, in the form of some simple APIs we can invoke to call the Push Notification permission, and register a device token. This package also provides support for Android notifications in the event you want one unified package to support both iOS and Android platforms.

: A simple wrapper for React Native that provides both Local and Remote Notifications support, in the form of some simple APIs we can invoke to call the Push Notification permission, and register a device token. This package also provides support for Android notifications in the event you want one unified package to support both iOS and Android platforms. @react-native-community/push-notification-ios : The go-to package for React Native APN support, super-seeding the original PushNotificationIOS component the React Native team provided. react-native-push-notification actually depends on this package, that is called under the hood of its simplified interface.

These are both open source community packages that have enhanced and simplified the integration process of APNs — using both of them gives us a relatively simple means of supporting them in our React Native component tree.

Install the packages and link them to your native app in the process, along with updating your Pods:

Cocoapods is a dependency manager for Swift and Objective-C Cocoa projects, the packages of which often acting as a counterpart of React Native NPM packages that offer iOS feature support.

// install packages

yarn add react-native-push-notification

yarn add @react-native-community/push-notification-ios // link

react-native link react-native-push-notification // update Pods

cd ios && pod install

This installation process should be pain free, relying on pod to update your native dependencies. Even though the latest version of React Native supports automatic linking, I would still include the link command if you are unsure whether auto-linking is supported in your project.

Calling configure() to request permission

We can invoke the Request Permission dialogue by calling react-native-push-notification 's configure() method, that will bring up a prompt like the following:

Request Push Notifications Permission Dialogue Box

This will be the point at which the user allows or disallows the use of notifications. If “OK” is tapped, the device token will be registered and returned from configure() ’s onRegister event, allowing us to handle it as we please.

If the user has already accepted Push Notifications, configure() will trigger its onRegister event immediately, skipping the Request Permission dialogue.

Concretely, configure() will return the device token on every subsequent call, after the user has enabled Push Notifications.

The Usage section of the package outlines configure() ’s options, ranging from the permission object itself to event handlers. The following Gist is a minimal implementation that handles the registering of a device token, wrapping it in a configure() function:

To save duplicating the documentation, check out the Usage section of react-native-push-notification to check out all the options available.

The above relies on default value of true for requestPermissions , that will automatically invoke the Request Permission prompt. Upon the user accepting, onRegister is triggered, giving us the opportunity to handle the token as we please — that may include:

Sending it off to your server, perhaps at an apn/save route that will persist the device token in your database.

route that will persist the device token in your database. Persisting the device token locally on-device using AsyncStorage, that could prevent configure() to be called again on subsequent visits to the app in the event the device token already exists.

Putting configure() into a Context

Perhaps the most elegant way of implementing configure() is by putting it into a React Context, making it available for any component to invoke. If you wanted the dialogue to pop up once a user signs into your app for example, you could call configure() within a <Dashboard /> component.

Having all logic within a context component also keeps APN logic in one file.

To learn more about Context, check out another of my recently published articles that uses Context to make scroll-aware header transitions work: React Native & TypeScript: Scroll Aware Header Transitions.

The following Gist expands on the previous one, now defining an APNManager component housing an APNContext , in addition to a useApn() context hook.

Notice also that we are wrapping the component with Redux, that is providing an authentication token to the component. The component can now send a newly registered device token to the app server along with the user’s auth token, in order to persist the device token with that particular user account:

Now, if we wrap <APNManager /> around the entire app, all components will have the ability to call configure() , such as the aforementioned <Dashboard /> component that could make use of the useApn() context hook:

// dashboard calling configure() ...

import { useApn } from './APNManager' export const Dashboard = (props: any) => { const apn = useApn(); useEffect(() => {

apn.configure();

}, []); ...

}

useEffect() has been used in the above example, with an empty array for conditional updates— this means apn.configure() will only be called once after the component’s initial render.

The react-native-push-notification package does more than what this article has outlined, such as handle Local Notifications, as well as Scheduled Notifications. Check out the full documentation to see everything the package supports.

Including Xcode APN delegate methods

There is one more piece to the React Native puzzle for APNs, and that is implementing their corresponding Objective-C APIs within Xcode — the packages we have been utilising will use these APIs under the hood.

If we refer to the @react-native-community/push-notification-ios package’s documentation in the Updating AppDelegate.m section, all that is needed is to copy the import statements and delegate methods into your corresponding AppDelegate.m file.

Some of these methods may already be defined within your AppDelegate.m file — simply do not include them if this is the case, only copying the methods absent from your project.

For the last section of this piece, we will explore actually sending notifications server-side in a Node.js environment, using the APN Key generated earlier along with the registered device tokens from the device.