DEV Community

Dainy Jose
Dainy Jose

Posted on

Advanced Push & Local Notifications in React Native with Firebase and Notifee (Part 2)

In the first part of this series, we built a complete Firebase Cloud Messaging (FCM) setup for React Native using Firebase and Notifee.

Now, in Part 2, we’ll go deeper and explore:

  • πŸ“± Local notifications
  • ✨ Custom notification styles
  • ⏰ Triggers and scheduling
  • ⚑ Action buttons and backend integration
  • 🎧 Media and chat-style notifications
  • πŸ“Š Event tracking for every app state (Foreground, Background, Killed)

This part focuses on building a robust notification system that behaves consistently across app states β€” with fixes to ensure reliable delivery and accurate navigation.


πŸ“± 1. Local Notifications with Notifee

Local notifications are shown without FCM, usually triggered by in-app events β€” such as reminders or task completions.

import notifee, { AndroidImportance, TriggerType } from '@notifee/react-native';

// Simple local notification
async function showLocalNotification() {
  await notifee.requestPermission();

  const channelId = await notifee.createChannel({
    id: 'local',
    name: 'Local Notifications',
    importance: AndroidImportance.HIGH,
  });

  await notifee.displayNotification({
    title: "'NotifyMeApp Reminder',"
    body: 'Your scheduled task is ready!',
    android: {
      channelId,
      smallIcon: 'ic_launcher',
    },
  });
}
Enter fullscreen mode Exit fullscreen mode

You can call showLocalNotification() anywhere β€” even as a response to user actions or events.


⏰ 2. Notification Triggers

Notifee allows scheduled or event-based notifications.

Example: Trigger after 10 seconds

const trigger = {
  type: TriggerType.TIMESTAMP,
  timestamp: Date.now() + 10 * 1000, // 10 seconds later
};

await notifee.createTriggerNotification(
  {
    title: 'NotifyMeApp',
    body: '⏰ Scheduled notification fired!',
    android: { channelId: 'local' },
  },
  trigger
);
Enter fullscreen mode Exit fullscreen mode

Example: Repeat daily reminder

const trigger = {
  type: TriggerType.INTERVAL,
  interval: 24 * 60 * 60, // every 24 hours
};

await notifee.createTriggerNotification(
  {
    title: 'Daily Reminder',
    body: 'It’s time to check new updates!',
    android: { channelId: 'local' },
  },
  trigger
);
Enter fullscreen mode Exit fullscreen mode

🧱 3. Customizing Notifications

You can completely customize your notification look using Notifee’s Android styles.

Big Picture Style (with Image)

await notifee.displayNotification({
  title: 'New Offer Available πŸŽ‰',
  body: 'Get 20% off on your next rental!',
  android: {
    channelId: 'promo',
    style: {
      type: notifee.AndroidStyle.BIGPICTURE,
      picture: 'https://example.com/offer-banner.jpg',
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

Messaging Style (for Chat)

await notifee.displayNotification({
  title: 'John Doe',
  body: 'Hey! Are you available for the shoot tomorrow?',
  android: {
    channelId: 'chat',
    style: {
      type: notifee.AndroidStyle.MESSAGING,
      person: { name: 'John Doe' },
      messages: [
        { text: 'Hey! Are you available for the shoot tomorrow?', timestamp: Date.now() },
      ],
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

βš™οΈ 4. Notification Actions (with Backend Support)

Add buttons directly to your notifications to trigger specific actions.

<!-- AndroidManifest.xml -->
<activity android:name=".MainActivity">
  <intent-filter>
    <action android:name="OPEN_ACTIVITY_1" />
    <category android:name="android.intent.category.DEFAULT" />
  </intent-filter>
</activity>
Enter fullscreen mode Exit fullscreen mode

Then in your notification payload (from backend):

const message = {
  token,
  notification: {
    title: 'NotifyMeApp',
    body: 'New message received',
  },
  android: {
    channelId: 'chat',
    actions: [
      {
        title: 'Reply',
        pressAction: {
          id: 'OPEN_ACTIVITY_1',
        },
      },
    ],
  },
};
Enter fullscreen mode Exit fullscreen mode

In your app:

notifee.onForegroundEvent(({ type, detail }) => {
  if (type === notifee.EventType.ACTION_PRESS && detail.pressAction.id === 'OPEN_ACTIVITY_1') {
    console.log('User tapped Reply button');
    // Backend can be notified here (e.g., mark as read or open chat)
  }
});
Enter fullscreen mode Exit fullscreen mode

🧠 5. Notification Events Across App States

Recent improvements have made notifications behave consistently across all app states.
Here’s how you can handle each transition cleanly πŸ‘‡

Received In Opened From Expected Behavior
Foreground Foreground Show custom in-app popup or Notifee local notification
Foreground Background Navigate to target screen after resume
Foreground Killed Use getInitialNotification() to handle navigation
Background Foreground Auto-navigate to notification target
Background Background Open directly to target screen
Background Killed Retrieve data from FCM launch event
Killed Foreground Fetch from last FCM message using onNotificationOpenedApp
Killed Background Same as above β€” delayed navigation allowed
Killed Killed Delivered silently; handle upon next app launch

Implementation Example

import messaging from '@react-native-firebase/messaging';
import notifee from '@notifee/react-native';
import { navigationRef } from './NavigationService';

// Foreground messages
messaging().onMessage(async (remoteMessage) => {
  await notifee.displayNotification({
    title: remoteMessage.notification?.title,
    body: remoteMessage.notification?.body,
    android: { channelId: 'default' },
  });
});

// When app is opened from background
messaging().onNotificationOpenedApp((remoteMessage) => {
  const screen = remoteMessage.data?.targetScreen;
  if (screen) navigationRef.current?.navigate(screen);
});

// When app is launched from a killed state
messaging()
  .getInitialNotification()
  .then((remoteMessage) => {
    if (remoteMessage) {
      const screen = remoteMessage.data?.targetScreen;
      if (screen) navigationRef.current?.navigate(screen);
    }
  });
Enter fullscreen mode Exit fullscreen mode

🎧 6. Media & Chat Notifications

To include images, videos, or chat previews inside notifications:

await notifee.displayNotification({
  title: '🎬 Video Upload Complete!',
  body: 'Your project is now ready to share.',
  android: {
    channelId: 'media',
    style: {
      type: notifee.AndroidStyle.BIGPICTURE,
      picture: 'https://example.com/video-thumbnail.jpg',
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

For chat-like experience:

await notifee.displayNotification({
  title: 'Anna',
  body: 'Hey! New project details are ready!',
  android: {
    channelId: 'chat',
    style: {
      type: notifee.AndroidStyle.MESSAGING,
      person: { name: 'Anna' },
      messages: [
        { text: 'Hey! New project details are ready!', timestamp: Date.now() },
        { text: 'Let’s discuss soon.', timestamp: Date.now() },
      ],
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

βœ… Key Fixes and Improvements

In the latest implementation:

  • Notifications tapped from a killed state now navigate correctly.
  • Foreground notifications no longer duplicate when both FCM and Notifee handlers are active.
  • Deep links from background notifications navigate smoothly on resume.

Resolved by:

  • Using getInitialNotification() for cold starts
  • Ensuring single Notifee channel creation
  • Separating local + FCM handlers
  • Maintaining event order for consistent navigation

🎯 Wrapping Up

In this advanced guide, we covered:

  • Local & scheduled notifications
  • Trigger-based alerts
  • Media and chat-style notifications
  • Custom action buttons integrated with backend
  • Complete event handling across all app states

Together with Part 1, you now have a production-ready notification system for any React Native app.


✍️ Written by Dainy Jose β€” Mobile App Developer specialized in React Native and the MERN stack.

πŸ’Ό Skills & Tools:

Mobile App Dev | MERN Stack | React Native | TypeScript | Redux | React.js | Node.js | MongoDB | MySQL | Express.js | REST API | JWT | Google Maps | Firebase | Jest | Agile | SDLC | Payments | Git | Bitbucket | Jira

πŸ“¬ Connect with me:

πŸ”— LinkedIn
πŸ’» GitHub
🌐 Portfolio

Top comments (0)