🔔 React Native Notifications: Your App’s Friendly Messenger
Analogy: Think of notifications like a postman who delivers messages to your phone. Sometimes messages come from far away (push notifications), sometimes you write yourself a reminder note (local notifications), and the postman sorts them into different mailboxes (channels) to keep things organized!
📬 What Are Notifications?
Imagine your phone is a house. Notifications are like little notes that pop up on your door, telling you something important!
Real Life Examples:
- 📱 “Your pizza is on the way!” — from a food delivery app
- 💬 “Mom sent you a message” — from a chat app
- ⏰ “Time to drink water!” — a reminder you set yourself
In React Native, we can send these helpful notes to our users!
🚀 Push Notification Setup
What Are Push Notifications?
Push notifications are messages sent from far away servers to your phone — like getting a letter from another city!
graph TD A["Your Server"] -->|Sends message| B["Push Service"] B -->|Firebase/APNs| C[User's Phone] C -->|Shows| D["Notification!"]
Setting Up Push Notifications
Step 1: Install the library
// Install expo-notifications
npx expo install expo-notifications
Step 2: Get Permission First!
Just like asking “May I come in?” before entering someone’s house:
import * as Notifications from
'expo-notifications';
async function askPermission() {
const { status } = await
Notifications
.requestPermissionsAsync();
if (status === 'granted') {
console.log('Yay! We can send notes!');
}
}
Step 3: Get Your Unique Token
This is like your phone’s special address so messages find you:
async function getToken() {
const token = await
Notifications
.getExpoPushTokenAsync();
console.log('My address:', token.data);
// "ExponentPushToken[xxx...]"
return token;
}
🎯 Simple Example
// Full setup in one place
import * as Notifications from
'expo-notifications';
export async function setupPush() {
// 1. Ask permission
const { status } = await
Notifications
.requestPermissionsAsync();
if (status !== 'granted') {
alert('Please allow notifications!');
return;
}
// 2. Get token for this device
const token = await
Notifications
.getExpoPushTokenAsync();
// 3. Send token to your server
await sendTokenToServer(token.data);
}
🏠 Local Notifications
What Are Local Notifications?
Local notifications are like sticky notes you write yourself. They don’t come from the internet — your phone creates them!
Perfect for:
- ⏰ Reminders (“Take your medicine at 3 PM!”)
- 📅 Scheduled alerts (“Meeting in 10 minutes”)
- ✅ Task completions (“Download finished!”)
Sending Your First Local Notification
import * as Notifications from
'expo-notifications';
async function sendReminder() {
await Notifications
.scheduleNotificationAsync({
content: {
title: "Hey there! 👋",
body: "Don't forget to smile today!",
},
trigger: null, // Shows immediately!
});
}
Scheduled Notifications
Want a note to appear later? Set a timer!
// Remind me in 5 seconds
await Notifications
.scheduleNotificationAsync({
content: {
title: "5 seconds passed! ⏱️",
body: "Time flies when you're coding!",
},
trigger: {
seconds: 5,
},
});
// Remind me at a specific time
await Notifications
.scheduleNotificationAsync({
content: {
title: "Good morning! ☀️",
body: "Time to start your day!",
},
trigger: {
hour: 8,
minute: 0,
repeats: true, // Every day!
},
});
📁 Notification Channels (Android)
What Are Channels?
Channels are like different mailboxes for different types of mail:
- 📮 One box for bills
- 📮 One box for letters from friends
- 📮 One box for magazines
On Android, users can control each mailbox separately!
graph TD A["Your App"] --> B["Messages Channel"] A --> C["Reminders Channel"] A --> D["Promotions Channel"] B -->|User can| E["Keep ON ✓"] C -->|User can| F["Keep ON ✓"] D -->|User can| G["Turn OFF ✗"]
Creating Channels
import * as Notifications from
'expo-notifications';
// Create a channel for messages
await Notifications
.setNotificationChannelAsync(
'messages',
{
name: 'Messages',
importance:
Notifications.AndroidImportance.HIGH,
sound: 'default',
vibrationPattern: [0, 250, 250, 250],
}
);
// Create a channel for reminders
await Notifications
.setNotificationChannelAsync(
'reminders',
{
name: 'Reminders',
importance:
Notifications.AndroidImportance.DEFAULT,
sound: 'gentle_bell.wav',
}
);
Using Channels
// Send to specific channel
await Notifications
.scheduleNotificationAsync({
content: {
title: "New Message! 💬",
body: "Sarah sent you a photo",
channelId: 'messages', // Goes here!
},
trigger: null,
});
📊 Importance Levels
| Level | What Happens |
|---|---|
| MAX | Pops up on screen! |
| HIGH | Makes sound + shows |
| DEFAULT | Sound, no popup |
| LOW | Silent, in tray |
| MIN | Hidden, no sound |
🎧 Notification Handlers
What Are Handlers?
Handlers are like helpers waiting at the door to deal with notes when they arrive:
- One helper receives the note (foreground handler)
- One helper responds when you tap the note (response handler)
Foreground Handler
“What happens when a note arrives while you’re using the app?”
import * as Notifications from
'expo-notifications';
// Set up the door helper
Notifications
.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true, // Show it!
shouldPlaySound: true, // Ding!
shouldSetBadge: true, // Red dot!
}),
});
Response Handler
“What happens when you tap on a notification?”
import { useEffect } from 'react';
import * as Notifications from
'expo-notifications';
function App() {
useEffect(() => {
// Listen for taps
const subscription =
Notifications
.addNotificationResponseReceivedListener(
response => {
const data =
response.notification
.request.content.data;
console.log('User tapped!', data);
// Navigate somewhere or do action
}
);
// Clean up
return () => subscription.remove();
}, []);
}
Received Handler
“What happens when notification arrives (foreground)?”
useEffect(() => {
const subscription =
Notifications
.addNotificationReceivedListener(
notification => {
console.log('Got a note!');
console.log(notification.request
.content.title);
}
);
return () => subscription.remove();
}, []);
📦 Notification Data
What Is Notification Data?
Data is like a secret message inside the envelope. The title and body are what everyone sees, but data is the hidden stuff your app uses!
graph LR A["Notification"] --> B["title: visible"] A --> C["body: visible"] A --> D["data: hidden magic ✨"]
Sending Data
await Notifications
.scheduleNotificationAsync({
content: {
title: "Order Update 📦",
body: "Your package is here!",
data: {
// Secret stuff for your app!
orderId: "12345",
screen: "OrderDetails",
action: "view",
},
},
trigger: null,
});
Reading Data
// When user taps the notification
const subscription =
Notifications
.addNotificationResponseReceivedListener(
response => {
// Get the secret data
const { orderId, screen } =
response.notification
.request.content.data;
// Use it!
if (screen === 'OrderDetails') {
navigation.navigate(screen, {
orderId
});
}
}
);
🎯 Complete Data Example
// Send a chat notification
async function sendChatNotification(
message
) {
await Notifications
.scheduleNotificationAsync({
content: {
title: `${message.senderName}`,
body: message.text,
data: {
type: 'chat',
chatId: message.chatId,
senderId: message.senderId,
timestamp: Date.now(),
},
},
trigger: null,
});
}
// Handle when tapped
function handleTap(response) {
const data = response.notification
.request.content.data;
if (data.type === 'chat') {
// Open that specific chat!
openChat(data.chatId);
}
}
🎉 Putting It All Together
Here’s a complete notification setup for your app:
import { useEffect, useRef } from 'react';
import * as Notifications from
'expo-notifications';
// 1. Configure handler
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: true,
shouldSetBadge: true,
}),
});
export function useNotifications() {
const responseListener = useRef();
const notificationListener = useRef();
useEffect(() => {
// 2. Setup channels (Android)
setupChannels();
// 3. Request permission
registerForPushNotifications();
// 4. Listen for notifications
notificationListener.current =
Notifications
.addNotificationReceivedListener(
n => console.log('Received:', n)
);
// 5. Listen for taps
responseListener.current =
Notifications
.addNotificationResponseReceivedListener(
r => handleTap(r)
);
return () => {
Notifications.removeNotification
Subscription(
notificationListener.current
);
Notifications.removeNotification
Subscription(
responseListener.current
);
};
}, []);
}
async function setupChannels() {
await Notifications
.setNotificationChannelAsync(
'default', {
name: 'Default',
importance: Notifications
.AndroidImportance.HIGH,
}
);
}
async function registerForPushNotifications() {
const { status } = await
Notifications.requestPermissionsAsync();
if (status === 'granted') {
const token = await
Notifications.getExpoPushTokenAsync();
console.log('Token:', token.data);
}
}
📝 Quick Summary
| Feature | What It Does | Like… |
|---|---|---|
| Push Setup | Get messages from servers | Mail from far away |
| Local | Create your own reminders | Sticky notes |
| Channels | Organize notification types | Different mailboxes |
| Handlers | React to notifications | Door helpers |
| Data | Hidden info for your app | Secret messages |
🚀 You Did It!
Now you know how to:
- ✅ Set up push notifications
- ✅ Create local reminders
- ✅ Organize with channels
- ✅ Handle notification events
- ✅ Pass data through notifications
Your app can now talk to your users like a friendly postman! 📬✨
