Simplify Mobile Push Notifications With Expo

   Front End Development
Simplify Mobile Push Notifications with Expo

Push notifications are an integral part of mobile app development these days, but many developers, myself included, cannot even think about implementing them without breaking into a cold sweat. Alright, maybe I’m exaggerating a bit, but I’ve never had fun with them before, until now.

Enter Expo. Expo is an amazing set of tools that vastly simplifies native development on iOS and Android. You don’t need Xcode, Android Studio, or any special hardware. Heck, you don’t even need a USB cable to connect your phone to your computer, and you can still use native features like the vibration API, the device payment API, Push Notifications, and publish your app to the app stores.

Getting Started

To demonstrate notifications, we will use Create React Native App, easily installable via yarn or npm. The following directions are paraphrased from their excellent getting started tutorial. Run either npm install -g create-react-native-app or yarn global add create-react-native-app.
To create a new app, run the following command, where “push-demo” is the name of the app, and consequently the directory created.

$ create-react-native-app push-demo
$ cd push-demo 

To run it on your phone, download the Expo Client app from your app store, then run npm start or yarn start, and scan the QR code from your terminal using the Expo app. Voila, a native app, running on your phone.

Register for notifications

The first thing we have to do, now that we have an app initialized, is to deal with registering push notifications. This process gets an app specific device token (special word for unique, scary looking string) from the Apple Push Notification service (APNs) or Google Cloud Messaging (GCM/FCM). However, Expo takes care of most of this for us, and all we have to do is:

async registerForPushNotifications() {
  const { status } = await Permissions.getAsync(Permissions.NOTIFICATIONS);

  if (status !== 'granted') {
    const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS);
    if (status !== 'granted') {

  const token = await Notifications.getExpoPushTokenAsync();

  this.subscription = Notifications.addListener(this.handleNotification);


This function takes care of the multiple states of permission grants a device can have. You can already have permissions for notifications granted, not yet granted, or declined. Next, it requests a push token from Expo, asynchronously. Then it defines a notification handler, in case the notification is sent while the app is in foreground, and finally it sets the token in the component state for use in the UI and in other functions. Now that we have a device token, we can use that to call Expo’s notification backend, which then calls APNS or GCM.

Send your first push notification

Expo has great documentation for this, but come on, I don’t want to have to set up a server and database just to test push notifications! However, Expo’s docs mention a direct HTTP/2 API, and give a cURL command so let’s try that directly from the device. To achieve this, we can write another function to send a push notification, given a token, title, and body.

sendPushNotification(token = this.state.token, title = this.state.title, body = this.state.body) {
  return fetch('', {
    body: JSON.stringify({
      to: token,
      title: title,
      body: body,
      data: { message: `${title} - ${body}` },
    headers: {
      'Content-Type': 'application/json',
    method: 'POST',

This function uses fetch to POST a JSON body containing the token and message to the Expo server. Combine this with some UI to allow entry of a title and body that you want the notification to display, and some conditionals to show the notification body when it is received, and we’re ready for a test!

The full source code for App.js can be found here.

The app has two buttons: a register and a send button. First, hit the register button and the device token field will show up. Then, hit the send button and your token and body from your input fields will be sent to Expo’s notification server, then to APNS or GCM as needed, and back to your phone using the token. Magic.

No provisioning profiles, certificates, keystores, entitlements, configurations, API keys, native IDEs, extra SDKs, or nightmares.

Where to go next

You can take this proof of concept in a lot of different directions. Thanks to Expo, all of this flow can be done on the device, if your target workflow is simple enough. But the next logical step would be to write a server side device token store. This way you can save the token with user information to be used later. You could even go as far as creating a UI dashboard to send notifications through, and to view and manage your users from.

In summary, all you have to do to get this working is:

  • $ create-react-native-app push-demo
  • $ cd push-demo
  • $ yarn start OR npm start
  • Copy & paste App.js into your project from here
  • Scan the QR code from Expo
  • Hit the register button
  • Hit the send button

This is just one of the many awesome features provided by Expo, and I encourage you to it check out the rest of its capabilities in the docs, which even include a guide on publishing to the app store. But hey, that’s another post!

This website uses cookies

These cookies are used to collect information about how you interact with our website and allow us to remember you. We use this information in order to improve and customize your browsing experience, and for analytics and metrics about our visitors both on this website and other media. To find out more about the cookies we use, see our Privacy Policy.

Please consent to the use of cookies before continuing to browse our site.

Like What You See?

Got any questions?