paint-brush
Integrating Push Notifications in your React Web App (CRA)by@AyoAlfonso
20,149 reads
20,149 reads

Integrating Push Notifications in your React Web App (CRA)

by Ayo AlfonsoDecember 4th, 2018
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Implementing push notifications for a react app is pretty straightforward until you have to do this on an app built with <a href="https://github.com/facebook/create-react-app" target="_blank">Create React App</a>, you might have a new service worker file to work with.

Company Mentioned

Mention Thumbnail

Coins Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - Integrating Push Notifications in your React Web App (CRA)
Ayo Alfonso HackerNoon profile picture

mobify.com

Implementing push notifications for a react app is pretty straightforward until you have to do this on an app built with Create React App, you might have a new service worker file to work with.

As someone modestly familiar with the folder structure of a CRA app you will know that this will cause conflicts or one service worker trying to overwrite the others.

It simply gets complicated.

Three reasons for this:

  1. Using the default scaffold flow for CRA npm run build, the service worker is generated automatically. Might take a while to understand all it is doing if you went through it now.
  2. You can not simply edit this file to include your firebase service worker methods and imports. You will have to do npm run ejectparticularly and that means you will have to be on your own onwards.
  3. You have to use Webpack plugins to generate the proper service worker when next you npm run build your project.

An example of this is the npm package ServiceWorkerWebpackPlugin

The way these plugins work is to release a dynamic service worker file in place of the default sw with a runtime helper.

The Solution

The alternative is to avoid modifying the default service worker in the root of your ./src and the one generated at the /build(we do not really have a business with this), it will most likely be named something like “registerServiceWorker.js”.

You should try to put your new service worker in the public/assets folder, this is the folder that is used to hold our assets. My service worker is named “firebase-messaging-sw.js”

The idea is that webpack will not bundle the js files in the public/assets folder unlike those in ./src and then we can call it and register it at the root of our react app.

I decided to structure my app like so:

On the initializePush() function we will be asking the users if they want us to be sending them notifications. And it is only called after registering/updating a service worker file.

A service worker is updated after the browser does a binary comparison between the old and new file; on finding a difference in output after the comparison it will install the new service worker and then generate a new token.

Below is the modal that shows on the first-ever request for permission to send push notifications to users.

Show notifications modal

And next getting the token based off your current instance of firebase. You will notice this function has the requestPermission() function and also the messaging.getToken() and then the sendTokenToServer() all in the .then() chain. Does this mean we are getting a new token from firebase every time we reach that point in the code?

Apparently, it turns out we don’t. We are not getting a new token every time the function is called. What actually happens is that the first time the getToken method is called, a network call is made, once retrieved and used (sent to our backend) subsequent calls to getToken() the token will return from the cache.

Extras

message.onMessage()

Receives messages sent to this client when the client has the app open.

self.addEventListener("notificationclick",()=>{})

Called when a client clicks on the notification that is sent from the app server somewhere.

message.setBackgroundMessageHandler

This method handles the messages received when a client does not have the app open.

Remember to instantiate your firebase instance in another directory, in case you missed it, it was used here; import messaging from 'config/firebase'

Goodluck!