7

I use React Native Firebase to receive notifications in React Native. When message is received in background and I click on notification, getInitialNotification will be triggered. If I navigate to another screen an than back to my HomeActivity, getInitialNotification will be fired again. How can I achieve to trigger it only once?

import React, { Component } from 'react';
import { StyleSheet, Platform, View, Text, YellowBox, Button } from 'react-native';
import StyleIndex from './css/StyleIndex';

import firebase from 'react-native-firebase';
import type { Notification, NotificationOpen } from 'react-native-firebase';


export default class HomeActivity extends Component {
  state = { currentUser: null }

componentDidMount() {
    const { currentUser } = firebase.auth()
    this.setState({ currentUser })

    var collectionReference = firebase.firestore().collection('users');
    var query = collectionReference.where("phone", "==", currentUser.phoneNumber);
    // console.log(firebase.messaging().getToken());
    firebase.messaging().hasPermission()
    .then(enabled => {
      if (enabled) {
        firebase.messaging().getToken().then(token => {
          query.get().then(function(querySnapshot) {
            if (querySnapshot.size == 1) {
              firebase.firestore().collection('users').doc(querySnapshot.docs[0].ref.id).update({
                fcmtoken: token,
              })
            } else {console.log('no or more than one documents found')}
          });
        })
        // user has permissions
      } else {
        firebase.messaging().requestPermission()
          .then(() => {
            alert("User Now Has Permission");
            console.log('now has permission');

          })
          .catch(error => {
            alert("Error", error)
            // User has rejected permissions  
          });
      }
    });
    this.onTokenRefreshListener = firebase.messaging().onTokenRefresh(fcmToken => {
      query.get().then(function(querySnapshot) {
        if (querySnapshot.size == 1) {
          firebase.firestore().collection('users').doc(querySnapshot.docs[0].ref.id).update({
            fcmtoken: fcmToken,


          })
          .catch(error => {
            alert("Error", error)
            // User has rejected permissions  
          });
      }
    });
    this.onTokenRefreshListener = firebase.messaging().onTokenRefresh(fcmToken => {
      query.get().then(function(querySnapshot) {
        if (querySnapshot.size == 1) {
          firebase.firestore().collection('users').doc(querySnapshot.docs[0].ref.id).update({
            fcmtoken: fcmToken,
          })
        } else {console.log('no or more than one documents found')}
      });
  });

 // DEFAULT CHANNEL
 const channel = new firebase.notifications.Android.Channel('default', 'Default Channel', firebase.notifications.Android.Importance.Max);
 channel.setDescription('My default channel');
 // Create the channel
 firebase.notifications().android.createChannel(channel);

 // data-only messages from FCM
 // https://rnfirebase.io/docs/v4.2.x/messaging/receiving-messages
 this.messageListener = firebase.messaging().onMessage((message) => {
   // Process your message as required
   console.log('onMessage', message);
 });

 // LOCAL NOTIFICATION: FOREGROUND
 this.notificationDisplayedListener = firebase.notifications().onNotificationDisplayed((notification: Notification) => {
   // Process your notification as required
   // ANDROID: Remote notifications do not contain the channel ID. You will have to specify this manually if you'd like to re-display the notification.
   console.log('onNotificationDisplayed', notification);
 });

 this.notificationListener = firebase.notifications().onNotification((notification: Notification) => {
   // Process your notification as required
   console.log('onNotification', notification);
   notification.android.setChannelId('default');
   notification.android.setAutoCancel(true);
   firebase.notifications().displayNotification(notification);
 });


 // APP FOREGROUND / BACKGROUND
 this.notificationOpenedListener = firebase.notifications().onNotificationOpened((notificationOpen: NotificationOpen) => {
   // Get the action triggered by the notification being opened
   const action = notificationOpen.action;
   console.log('onNotificationOpened - action', action);
   // Get information about the notification that was opened
   const notification: Notification = notificationOpen.notification;
   notification.android.setChannelId('default');

  //  firebase.notifications().displayNotification(notification);
   console.log('onNotificationOpened - notification', notification);

 firebase.notifications().displayNotification(notification)
 });

     // APP CLOSED
     firebase.notifications().getInitialNotification()
     .then((notificationOpen: NotificationOpen) => {
       if (notificationOpen) {
         // App was opened by a notification
         // Get the action triggered by the notification being opened
         const action = notificationOpen.action;
         console.log('getInitialNotification - action', action);
         // Get information about the notification that was opened
         const notification: Notification = notificationOpen.notification;
        //  notification.android.setChannelId('default');
         notification.android.setAutoCancel(true);        
         console.log('getInitialNotification - notification', notification);
         // Display the notification
        //  firebase.notifications().displayNotification(notification);
        alert('getInitialNotification');
         firebase.notifications().removeAllDeliveredNotifications();
         firebase.notifications().cancelAllNotifications();
       }
     });

  }
  componentWillUnmount() {
    this.onTokenRefreshListener();
    this.notificationDisplayedListener();
    this.notificationListener();
    this.notificationOpenedListener();
}
MajinMo
  • 541
  • 1
  • 5
  • 9
  • did you find any solution for this ? – Amila Dulanjana Nov 28 '18 at 07:28
  • Without knowing more of what your navigation is, I would guess you are using react navigation? If so, I'd also guess you are reseting your navigation stack, meaning HomeActivity is being mounted again. I'd say either reorganize your navigation so that navigating back to HomeActivity does not force a remount. If using some state management (context/redux), you can store the notificationIds in state and add a check that the notificationId does not exist in state before navigating. – Edward Smith Dec 07 '18 at 11:17
  • The notifications do not work when using simulators, it only works when the app is installed on real device using apk, ipa. I see that you have `console.log()` in your code. How do you see your `console.log()`? – Kasra Aug 10 '20 at 09:43

1 Answers1

1

The reason that the notification gets called in a loop is that you are calling firebase.notifications().displayNotification(notification); with a remote notification.

Instead you should create a new local notification, and show that instead of the the remote one.

const localNotification = new firebase.notifications.Notification({
          sound: "default",
          show_in_foreground: true
        })
          .setNotificationId(notification.notificationId)
          .setTitle(notification.title)
          .setSubtitle(notification.subtitle)
          .setBody(notification.body)
          .setData(notification.data)
          .android.setChannelId("notification_channel_id")
          .android.setPriority(firebase.notifications.Android.Priority.High);

firebase.notifications().displayNotification(localNotification);
Francois Nadeau
  • 7,023
  • 2
  • 49
  • 58
  • Hey Francois, can you check this Question please, @FrancoisNadeau https://stackoverflow.com/questions/57171787/navigate-to-screen-after-opening-a-notification – DevAS Jul 23 '19 at 22:08