Push notifications in Ionic-React

Hello,

Do you guys know any tutorial regarding how to implement push notifications (let’s say from firebase or OneSignal) in Ionic using React. All I can find is in Angular and I can’t understand it really well.

Thank you a lot!

Hi @jklr8 !

I’m interesting about that too!
Have you found any tutorial or something like this?

Cheers.
David.

This is not a tutorial, but here’s some code from an app I am working on (not released yet, but I have tested push notifications and they are working).

In index.tsx, you set up the push notificatoin listeners if the app is being used on a mobile platform:

const startApp = () => {
ReactDOM.render(, document.getElementById(‘root’));
};

if (isPlatformMobile()) {
  document.addEventListener('deviceready', () => {
    // Some issue with our setup and push will not work.
    PushNotifications.addListener('registrationError',
      (error: JSON) => {
        debugLog('push registration error', error);
      });

    // Show us the notification payload if the app is open on our device.
    // PushNotifications.addListener('pushNotificationReceived',
    //   (notification: PushNotificationSchema) => {
    //     alert(`Push received: ${JSON.stringify(notification)}`);
    //   });

    // Method called when tapping on a notification
    PushNotifications.addListener('pushNotificationActionPerformed',
      (notification: ActionPerformed) => {
        debugLog('push registration tapped', notification);
        babyLogMyNotificationTap(notification);
      });
  startApp();

Then you need a listener to save the push notification token when the user enables push notifications:

I put this in a listener component; I’m using Drupal as the backend, so I use the savePushToken() function (my custom function) to POST the token to Drupal. Of course, you should do whatever makes sense for your app here.

  useEffect(() => {
    if (platform.mobile) {
      PushNotifications.addListener('registration',
        (token: Token) => {
          debugLog('push token', token);
          savePushToken(token.value);
        });
    }
    return () => {
      if (platform.mobile) {
        PushNotifications.removeAllListeners();
      }
    };
  }, [platform.mobile]);

Here’s the code for the page where I request permission to use notifications:

const requestPermissionNotifications = (
  // @ts-ignore TS2315: Type 'History' is not generic.
  history: History<unknown>, queryClient: QueryClient,
) => {
  // Request permission to use push notifications.
  // iOS will prompt user and return if they granted permission or not.
  // Android will just grant without prompting.
  PushNotifications.requestPermissions().then((result) => {
    if (result.receive === 'granted') {
      debugLog('push notifications permission granted');
      // Register with Apple / Google to receive push via APNS/FCM.
      PushNotifications.register();
      history.push(goToNextPage);
    } else {
      queryClient.invalidateQueries(queryKeyPushNotificationsEnabled);
    }
  });
};

<IonButton
  onClick={() => {
    requestPermissionNotifications(history, queryClient);
  }}
>
  Continue
</IonButton>

Here’s how I check whether push notifications are enabled:

import { LocalNotifications } from '@capacitor/local-notifications';

// We need to use LocalNotifications, not PushNotifications,
// because Android will always return true for PushNotifications.
const arePushNotificationsEnabled = async (): Promise<PermissionState> => (
  LocalNotifications.checkPermissions()
    .then((response) => {
      // 'prompt-with-rationale' is not a PermissionState.
      if (response.display === 'prompt-with-rationale') {
        return ('prompt');
      }
      return (response.display);
    }));

export default arePushNotificationsEnabled;

Sorry it’s not more organized, but I know the documentation for React is a little lacking, so I thought some examples are better than nothing.

I did something like this and it works add these methods in App.tsx

const usePushNotifications = () => {
  const addListeners = useCallback(async () => {
    await PushNotifications.addListener('registration', (token) => {
      console.log('Registration token: ', token.value);
    });

    await PushNotifications.addListener('registrationError', (err) => {
      console.error('Registration error: ', err.error);
    });

    await PushNotifications.addListener('pushNotificationReceived', (notification) => {
      console.log('Push notification received: ', notification);
    });

    await PushNotifications.addListener('pushNotificationActionPerformed', (notification) => {
      console.log(
        'Push notification action performed',
        notification.actionId,
        notification.inputValue,
      );
    });
  }, []);

  const registerNotifications = useCallback(async () => {
    let permStatus = await PushNotifications.checkPermissions();

    if (permStatus.receive === 'prompt') {
      permStatus = await PushNotifications.requestPermissions();
    }

    if (permStatus.receive !== 'granted') {
      throw new Error('User denied permissions!');
    }

    await PushNotifications.register();
  }, []);

  const getDeliveredNotifications = useCallback(async () => {
    const notificationList = await PushNotifications.getDeliveredNotifications();
    console.log('delivered notifications', notificationList);
  }, []);

  return { addListeners, registerNotifications, getDeliveredNotifications };
}

Then add this in the useEffect method:

const App: React.FC = () => {
  const { addListeners, registerNotifications } = usePushNotifications();

  useEffect(() => {
    (async () => {
      await registerNotifications();
      await addListeners();
    })();
  }, [addListeners, registerNotifications]);