Show push notifications in React
Tags: javascript, react, programming, productivity
Published: 2021-07-25 09:09:46

*In case it helped :)*
<a href="https://www.buymeacoffee.com/aseemwangoo" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Pass Me A Coffee!!" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>

<!-- wp:paragraph -->
<p>We will go through the following steps</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>Register the web app in Firebase</li><li>Setup Firebase Configurations in React</li><li>Integrate in UI</li><li>Test the Notification</li><li>(<strong>Optional</strong>) If notifications not appearing</li></ol>
<!-- /wp:list -->

{% youtube rqBh4YP_CwM %}

<!-- wp:heading {"level":3} -->
<h3>Register the web app in&nbsp;Firebase</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Login into the Firebase <a href="https://console.firebase.google.com/u/0/" rel="noreferrer noopener" target="_blank">console</a> and click on <strong>Add project</strong>. Follow the steps to add the project.</p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center"} -->
<div class="wp-block-image"><figure class="aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/1*1BSWqGwrl-scxtpEAweZyA.png" alt="Register app with Firebase"/><figcaption>Register app with Firebase</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>After registering the app, you will get the following page.</p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center"} -->
<div class="wp-block-image"><figure class="aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/1*2yweGd9rIxfyNubLZBaMcg.png" alt="Config Page"/><figcaption>Config Page</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:paragraph -->
<p>We’ll be requiring this configuration in the next step.</p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":3} -->
<h3>Setup Firebase Configurations in&nbsp;React</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p><strong>This step is divided into the following sub steps.</strong></p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>Install the firebase dependency in the project using</li></ol>
<!-- /wp:list -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">npm install firebase</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>2. We will configure firebase, in our project. Create a file called <strong>firebaseInit.js (</strong>the name can be anything you want).&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:paragraph -->
<p>Inside this file, add the following lines</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>import firebase from 'firebase/app';
import 'firebase/messaging';
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
  apiKey: "YOUR_API_KEY",
  authDomain: "YOUR_AUTH_DOMAIN",
  projectId: "YOUR_PROJECT_ID",
  storageBucket: "YOUR_STORAGE_BUCKET",
  messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
  appId: "YOUR_APP_ID",
  measurementId: "YOUR MEASUREMENT ID"
};
firebase.initializeApp(firebaseConfig);</code></pre>
<!-- /wp:code -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Note: The above configuration can be found from your firebase project (Under <strong>Project Settings</strong> or from <strong>Step 1</strong>)</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>3. Inside this file, we will integrate the cloud messaging. But before jumping in, we need a key called <strong>VAPID key</strong></p>
<!-- /wp:paragraph -->

<!-- wp:heading {"level":4} -->
<h4>VAPID Key</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>According to the documentation</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>The FCM Web interface uses Web credentials called “Voluntary Application Server Identification,” or “VAPID” keys, to authorise send requests to supported web push services.&nbsp;</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>This key can either be generated or imported from your existing key pair through the Firebase Console.</p>
<!-- /wp:paragraph -->

<!-- wp:list {"ordered":true} -->
<ol><li>Open the <a href="https://console.firebase.google.com/project/_/settings/cloudmessaging/" rel="noreferrer noopener" target="_blank">Cloud Messaging</a> tab of the Firebase console <strong>Settings</strong> pane and scroll to the <strong>Web configuration</strong> section.</li><li>In the <strong>Web Push certificates</strong> tab, copy the <strong>Key pair</strong> (LHS Value in the screenshot below)</li></ol>
<!-- /wp:list -->

<!-- wp:image {"align":"center"} -->
<div class="wp-block-image"><figure class="aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/1*GwbqGZhu_ATiVorUYUZgDw.png" alt="Vapid key"/><figcaption>Vapid key</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>For more information about the format of the keys and how to generate them, see <a href="https://developers.google.com/web/fundamentals/push-notifications/web-push-protocol#application_server_keys" rel="noreferrer noopener" target="_blank">Application server keys</a>.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:paragraph -->
<p>Back to our <strong>firebaseInit.js, </strong>add these lines</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>const messaging = firebase.messaging();
const { REACT_APP_VAPID_KEY } = process.env
const publicKey = REACT_APP_VAPID_KEY;</code></pre>
<!-- /wp:code -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:heading {"level":4} -->
<h4>Notification permissions</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Before sending push notifications to the browser, we first need to get permission from the user. This is handled by the <code>getToken</code> method that firebase provides.</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>export const getToken = async (setTokenFound) => {
  let currentToken = '';
  try {
    currentToken = await messaging.getToken({vapidKey: publicKey});
    if (currentToken) {
      setTokenFound(true);
    } else {
      setTokenFound(false);
    }
  } catch (error) {
    console.log('An error occurred while retrieving token.', error);
  }
  return currentToken;
};</code></pre>
<!-- /wp:code -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:list -->
<ul><li>The method <code><a href="https://firebase.google.com/docs/reference/js/firebase.messaging.Messaging#getToken" rel="noreferrer noopener" target="_blank">getToken</a> </code>will ask the user for notification permissions, if they have not been granted. Otherwise, it returns a token or rejects the promise due to an error.</li><li>And we pass the vapid key from the previous step to <code>getToken</code>&nbsp;</li></ul>
<!-- /wp:list -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>After you’ve obtained the token, store it using your preferred method, in our case, <strong>we will just log in the console</strong>.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:heading {"level":4} -->
<h4>Set the Listeners (Foreground and Background)</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>When the app is active in <strong>foreground</strong>, we need to add this code to the <code>firebaseInit.js</code> file, so that we know the notification has received</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>export const onMessageListener = () =>
  new Promise((resolve) => {
    messaging.onMessage((payload) => {
      resolve(payload);
    });
  });</code></pre>
<!-- /wp:code -->

<!-- wp:heading {"level":4} -->
<h4>Background Listener</h4>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>In the scenario when the page is in background or hidden behind other tabs, we need to handle <code><a href="https://firebase.google.com/docs/reference/js/firebase.messaging.Messaging#onbackgroundmessage" rel="noreferrer noopener" target="_blank">onBackgroundMessage</a>.</code>&nbsp;</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>We do that by adding a <code>firebase-messaging-sw.js</code> <strong>service-worker</strong> file in the public folder of our react app. Add the following lines</li></ul>
<!-- /wp:list -->

<!-- wp:code -->
<pre class="wp-block-code"><code>importScripts("https://www.gstatic.com/firebasejs/8.2.0/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/8.2.0/firebase-messaging.js");
const firebaseConfig = {
  apiKey: "YOUR_API_KEY",
  authDomain: "YOUR_AUTH_DOMAIN",
  projectId: "YOUR_PROJECT_ID",
  storageBucket: "YOUR_STORAGE_BUCKET",
  messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
  appId: "YOUR_APP_ID",
  measurementId: "YOUR MEASUREMENT ID"
};
firebase.initializeApp(firebaseConfig);</code></pre>
<!-- /wp:code -->

<!-- wp:list -->
<ul><li>The first two import statements basically download the firebase libraries required for the service worker.</li><li>Next we configure our firebase app, using the firebase config (see above steps or your firebase project)</li><li>Finally, we handle the <code>onBackgroundMessage</code> inside the service worker file</li></ul>
<!-- /wp:list -->

<!-- wp:code -->
<pre class="wp-block-code"><code>const messaging = firebase.messaging();
messaging.onBackgroundMessage(function (payload) {
  console.log("Received background message ", payload);
  const notificationTitle = payload.notification.title;
    const notificationOptions = {
      body: payload.notification.body,
      icon: "/logo192.png",
  };
return self.registration.showNotification(
    notificationTitle,
    notificationOptions
  );
});</code></pre>
<!-- /wp:code -->

<!-- wp:heading {"level":3} -->
<h3>Integrate in&nbsp;UI</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Till now, we managed to configure the firebase inside our react app. Now, we will see how to integrate messaging in our UI.</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Inside our <code>App.js</code> we import the file <code>firebaseInit.js</code> and implement the <code>onMessageListener</code></li></ul>
<!-- /wp:list -->

<!-- wp:code -->
<pre class="wp-block-code"><code>const &#91;show, setShow] = useState(false);
const &#91;notification, setNotification]=useState({title:"",body:""});
onMessageListener()
   .then((payload) => {
      setShow(true);
      setNotification({
        title: payload.notification.title,
        body: payload.notification.body,
      });
      console.log(payload);
   })
.catch((err) => console.log("failed: ", err));</code></pre>
<!-- /wp:code -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Note: We use the <a href="https://reactjs.org/docs/hooks-state.html" rel="noreferrer noopener" target="_blank">useState</a> hooks, which determine when to show the notification.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:list -->
<ul><li>Next, we create a component called <code>Notifications.</code> This component is basically responsible for getting the token from the browser.</li></ul>
<!-- /wp:list -->

<!-- wp:code -->
<pre class="wp-block-code"><code>const Notifications = (props) => {
  const &#91;isTokenFound, setTokenFound] = useState(false);                
  console.log("Token found", isTokenFound);
  useEffect(() => {
    let data;
    async function tokenFunc() {
      data = await getToken(setTokenFound);
      if (data) {
        console.log("Token is", data);
      }
      return data;
    }
    tokenFunc();
  }, &#91;setTokenFound]);
  return &lt;>&lt;/>;
 };
export default Notifications;</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>Here, we call the <code>getToken</code> function, which is defined inside <code>firebaseInit.js</code> Once we get the token, we log it in the console.</p>
<!-- /wp:paragraph -->

<!-- wp:quote -->
<blockquote class="wp-block-quote"><p>Note: We use the <a href="https://reactjs.org/docs/hooks-effect.html" rel="noreferrer noopener" target="_blank">useEffect</a> hook, since we don’t want to call the getToken repeatedly.</p></blockquote>
<!-- /wp:quote -->

<!-- wp:list -->
<ul><li>Lastly, we create another component called <code>ReactNotificationComponent</code> which basically shows the notification, when the app is in foreground.</li></ul>
<!-- /wp:list -->

<!-- wp:code -->
<pre class="wp-block-code"><code>import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
const ReactNotificationComponent = ({ title, body }) => {
  toast.info(&lt;Display />);
  function Display() {
    return (
      &lt;div>
        &lt;h4>{title}&lt;/h4>
        &lt;p>{body}&lt;/p>
      &lt;/div>
    );
  }
  return (
    &lt;ToastContainer />
  );
};</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>This basically displays the notification using the library <a href="https://www.npmjs.com/package/react-toastify" rel="noreferrer noopener" target="_blank"><strong>react-toastify</strong></a><strong>. </strong>We pass in the parameters, title and body from the <code>App.js</code></p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center"} -->
<div class="wp-block-image"><figure class="aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/1*eEBFUjGoeFlyLSY8j3PWcQ.png" alt="Foreground Notification display"/><figcaption>Foreground Notification display</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:heading {"level":3} -->
<h3>Test the Notification</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Start your react project by</p>
<!-- /wp:paragraph -->

<!-- wp:preformatted -->
<pre class="wp-block-preformatted">npm run start</pre>
<!-- /wp:preformatted -->

<!-- wp:paragraph -->
<p>Inside your firebase console, go to <strong>Cloud messaging</strong> section of the app</p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center"} -->
<div class="wp-block-image"><figure class="aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/1*PUsnnBuI-VTwgx364AH_xA.png" alt="Cloud Messaging"/><figcaption>Cloud Messaging</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:list {"ordered":true} -->
<ol><li>Click the button <strong>Send your first message</strong>.</li><li>Enter the notification title and text.</li><li>Select <strong>Send test message</strong>.</li><li>In the field labeled <strong>Add an FCM registration token</strong>, enter the registration token you obtained from previous step.</li><li>Click <strong>Test</strong></li></ol>
<!-- /wp:list -->

<!-- wp:paragraph -->
<p>After you click <strong>Test</strong>, your app should receive the notification in the browser.</p>
<!-- /wp:paragraph -->

<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->

<!-- wp:heading {"level":3} -->
<h3>If notifications not appearing</h3>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>There are times, when things don’t work, and hence this section exists. Following are some points which you can check (<strong>for macOS</strong>), in case notifications don’t work for you:</p>
<!-- /wp:paragraph -->

<!-- wp:list -->
<ul><li>Check for the notification permission in the browser. The Notifications should be set to <strong>Allow</strong></li></ul>
<!-- /wp:list -->

<!-- wp:image {"align":"center","width":642,"height":742} -->
<div class="wp-block-image"><figure class="aligncenter is-resized"><img src="https://cdn-images-1.medium.com/max/1600/1*x5ztvXkyAG2Yxu1yfnBjDQ.png" alt="Browser Notification Permission" width="642" height="742"/><figcaption>Browser Notification Permission</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:list -->
<ul><li>Your <strong>Do Not Disturb</strong> should be turned off</li></ul>
<!-- /wp:list -->

<!-- wp:image {"align":"center"} -->
<div class="wp-block-image"><figure class="aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/1*zit9eRyCTXXQZ-RhQ_Orzw.png" alt="Do Not Disturb"/><figcaption>Do Not&nbsp;Disturb</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:list -->
<ul><li>Go to the chrome settings, and search for notifications, verify if the option<strong> Sites can ask to send notifications</strong> is selected.</li></ul>
<!-- /wp:list -->

<!-- wp:image {"align":"center"} -->
<div class="wp-block-image"><figure class="aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/1*Dmwabf1TSwsyF_G0L0XtMA.png" alt="Chrome Settings"/><figcaption>Chrome Settings</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:list -->
<ul><li>Open the Spotlight Search and go to <strong>SystemPreferences -&gt; Notification Centre Settings. </strong>Check if the notifications are turned on for Chrome</li></ul>
<!-- /wp:list -->

<!-- wp:image {"align":"center"} -->
<div class="wp-block-image"><figure class="aligncenter"><img src="https://cdn-images-1.medium.com/max/1600/1*YzKHwptbaCO3QPr9V1JByg.png" alt="Notification Centre Settings"/><figcaption>Notification Centre&nbsp;Settings</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:list -->
<ul><li>Notifications show twice, for this we will need to remove the React.strictMode from our <code>index.js</code>&nbsp;. Refer <a href="https://stackoverflow.com/questions/66263996/react-app-my-alert-window-is-showing-up-twice" rel="noreferrer noopener" target="_blank">link</a>.</li></ul>
<!-- /wp:list -->

{% youtube rqBh4YP_CwM %}

*In case it helped :)*
<a href="https://www.buymeacoffee.com/aseemwangoo" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Pass Me A Coffee!!" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>

<!-- wp:paragraph -->
<p><a rel="noreferrer noopener" href="https://github.com/AseemWangoo/expriments_with_react" target="_blank"><em>Source code.</em></a>

<!-- wp:paragraph -->
<p><strong><em>Website: </em></strong><a href="https://funwithreact.web.app/" rel="noreferrer noopener" target="_blank"><strong><em>https://funwithreact.web.app/</em></strong></a></p>