FCM Integration in react and node (Part -1)
Tags: firebase, pubsub, node, react
Published: 2022-06-10 11:08:30

So, I have surfed a web for quite some time for FCM and gone through documentation as well but i could not found the one stop solution.

Here we go.

Integration with React

This is quite simple and straight forward.

I believe you do have the project ready if not

`npx create-react-app fcm-client`

Here is the tricky part - To work with notification you need a device token APN token.(App registration on specific device) for that we need to convert your app into a PWA. But, create-react-app has removed the service workers from the initial repo. To use service workers 

`npx create-react-app fcm-client --template cra-template-pwa`

refer [https://create-react-app.dev/docs/making-a-progressive-web-app/](https://create-react-app.dev/docs/making-a-progressive-web-app/)

This will create app with service worker.

Once this is complete go to firebase console and set up a new project (Assuming you will do it on your own)

Go to project settings->cloud messaging->web push certificate 
and generate the key pair (will be needing to generate device token)

![firebase setting page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fy4900ry434a3b4949zr.png)

`npm install bootstrap react-bootstrap`

Go to App.js and paste below code
This will create a bootstrap toaster to display

```
import logo from './logo.svg';
import './App.css';
import {useState} from 'react';
import {Button, Row, Col, Toast} from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';

function App() {

const [show, setShow] = useState(false);


  return (
    <div className="App">
        <Toast onClose={() => setShow(false)} show={show} delay={3000} autohide animation style={{
          position: 'absolute',
          top: 20,
          right: 20,
        }}>
          <Toast.Header>
            <img
              src="holder.js/20x20?text=%20"
              className="rounded mr-2"
              alt=""
            />
            <strong className="mr-auto">Notification</strong>
            <small>5 mins ago</small>
          </Toast.Header>
          <Toast.Body>There are some new updates that you might love!</Toast.Body>
        </Toast>
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <Button onClick={() => setShow(true)}>Show Toast</Button>
      </header>
    </div>
  );
}

export default App;

```

Now create a new file in src directory `firebase.js` and copy below code

```
import { initializeApp } from 'firebase/app';
import { getMessaging, getToken, onMessage } from "firebase/messaging";


const firebaseConfig = {
    apiKey: API_KEY,
    authDomain: AUTH_DOMAIN,
    projectId: PROJECT_ID,
    storageBucket: STORAGE_BUCKET,
    messagingSenderId: MESSAGING_SENDER_ID,
    appId: APP_ID,
    measurementId: MEASUREMENT_ID
};

const firebaseApp = initializeApp(firebaseConfig);
const messaging = getMessaging(firebaseApp);
```

Import firebase.js in your App.js

next create a new file in public directory called `firebase-messaging-sw.js` and keep it empty for now

`npm run start` 

This is how your screen will look like 

![Landing screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4veb8y6lyelj6qid40iq.png)


Now its time to generate token

go to firebase.js and create new function which will request a permission from a user 

```
const messaging = getMessaging(firebaseApp);


export const getTokens = async (setTokenFound) => {
//VAPID_KEY is the Web push certificates key pair
    return getToken(messaging, {vapidKey: VAPID_KEY }).then((currentToken) => {
        if (currentToken) {
            console.log('current token for client: ', currentToken);
            setTokenFound(true);
            // Track the token -> client mapping, by sending to backend server
            // show on the UI that permission is secured
        } else {
            console.log('No registration token available. Request permission to generate one.');
            setTokenFound(false);
            // shows on the UI that permission is required 
        }
    }).catch((err) => {
    console.log('An error occurred while retrieving token. ', err);
    // catch error while creating client token
});
}
```

For VAPID_KEY we already have a key if you remember we generated key above from firebase console use that key here

Now back to App.js and add the below code

```
import {getTokens} from './firebase'

// Inside a App function Just to be sure 😅
const [isTokenFound, setTokenFound] = useState(false);
getTokens(setTokenFound);
```
Now open you devtool and check console you will have token if not there are might be error saying Permission denied.

Ok this is the part is bit interesting you can manually unable the notification allow from i button before URL 

![Allow Notification Permission](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qqihf4gxo5akzxn0rk0c.png)
 
But the interesting part is you can change your `localhost:3000` to `127.0.0.1:3000` and it will ask you for a permission on chrome but both will work on firefox 


![Permission Request from Browser](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z8hptf59abvdzkv031es.png)

Perfect All seems working till this point and you might have a token as well but now we want to see the notification from the server

go to `firebase-messaging-sw.js` and copy below code

```
// Scripts for firebase and firebase messaging
importScripts('https://www.gstatic.com/firebasejs/8.2.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.2.0/firebase-messaging.js');

// Initialize the Firebase app in the service worker by passing the generated config
const firebaseConfig = {
    apiKey: API_KEY,
    authDomain: AUTH_DOMAIN,
    projectId: PROJECT_ID,
    storageBucket: STORAGE_BUCKET,
    messagingSenderId: MESSAGING_SENDER_ID,
    appId: APP_ID,
    measurementId: MEASUREMENT_ID
};

firebase.initializeApp(firebaseConfig);

// Retrieve firebase messaging
const messaging = firebase.messaging();

messaging.onBackgroundMessage(function(payload) {
  console.log('Received background message ', payload);
 // Customize notification here
  const notificationTitle = payload.notification.title;
  const notificationOptions = {
    body: payload.notification.body,
  };

  self.registration.showNotification(notificationTitle,
    notificationOptions);
});
```

Now go to src->firebase.js and paste a listener function

```
export const onMessageListener = () =>
  new Promise((resolve) => {
    onMessage(messaging, (payload) => {
      console.log("payload", payload)
      resolve(payload);
    });
  });
```

back to App.js and add use the newly created listener

```
import {getTokens, onMessageListener} from './firebase'

// Inside APP function
onMessageListener().then(payload=>{
  console.log(payload)
  setShow(true)
}).catch(err=>console.log(err))
```

All good Awesome we are ready to receive our first message

Go to firebase console and inside `engage->cloud messaging->send your first message`

![Firebase Cloud Messaging First message screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7x7usyghn7168msyd1f8.png)
 
Add the requred details only and click on Send Test Message it will show a modal with asking for FCM Registration Token Like this

![Asking FCM Token](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/br6fzq67xeqw615t1nji.png)
 
Here you add the token from your web console that we just generated before. This is your device token which firebase server will understand which device to send a notification And viola You will receive a notification.

Note- Notification will not show the same text as we have entered in firebase since we have configured the static text for demo purpose.

This is the front end part for the backend part i will create part 2 post which will cover server side notifications using firebase-admin and also subscriptions

Hope it was useful.