React Native course ยท Module 7: Notifications
Push Notifications
In this lesson4
Push notifications are sent from a server to the user's device.
Expo Push Service
// On the server (Node.js)
import { Expo, ExpoPushMessage } from 'expo-server-sdk';
const expo = new Expo();
async function sendPushNotification(pushToken: string, title: string, body: string) {
const message: ExpoPushMessage = {
to: pushToken,
sound: 'default',
title,
body,
data: { someData: 'goes here' },
};
const chunks = expo.chunkPushNotifications([message]);
const tickets = [];
for (const chunk of chunks) {
const ticketChunk = await expo.sendPushNotificationsAsync(chunk);
tickets.push(...ticketChunk);
}
return tickets;
}Sending with curl (testing)
curl -H "Content-Type: application/json" -X POST \
"https://exp.host/--/api/v2/push/send" \
-d '{
"to": "ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]",
"title":"Message from Atlantis",
"body": "Poseidon summons you!"
}'Storing Token on Server
// In the app - after user registration
async function savePushToken() {
const token = await registerForPushNotificationsAsync();
if (token) {
// Send token to your server
await fetch('https://api.atlantis.app/users/push-token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
token: token.data,
platform: Platform.OS,
}),
});
}
}Handling Received Notifications
import { useEffect, useRef } from 'react';
import * as Notifications from 'expo-notifications';
function useNotifications() {
const notificationListener = useRef<Notifications.Subscription>();
const responseListener = useRef<Notifications.Subscription>();
useEffect(() => {
// Listener for received notification (app in foreground)
notificationListener.current = Notifications.addNotificationReceivedListener(
(notification) => {
console.log('Received:', notification);
}
);
// Listener for notification interaction
responseListener.current = Notifications.addNotificationResponseReceivedListener(
(response) => {
const data = response.notification.request.content.data;
console.log('Notification tapped:', data);
// Navigate based on data
if (data.screen) {
navigation.navigate(data.screen, data);
}
}
);
return () => {
notificationListener.current?.remove();
responseListener.current?.remove();
};
}, []);
}Push notifications allow communication with the user even when the app is closed!
Code for this lesson: App.tsx
import { useEffect, useRef, useState } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import * as Notifications from 'expo-notifications';
// Hook handling notification receipt and tap
function useNotifications() {
const [lastNotification, setLastNotification] = useState<string>('');
const notificationListener = useRef<Notifications.Subscription>();
const responseListener = useRef<Notifications.Subscription>();
useEffect(() => {
// TODO: listener for a received notification (app in foreground)
// use Notifications.addNotificationReceivedListener
notificationListener.current = Notifications.addNotificationReceivedListener(
(notification) => {
// TODO: save the notification title into state
setLastNotification('');
}
);
// TODO: listener for tapping/interacting with the notification
// use Notifications.addNotificationResponseReceivedListener
responseListener.current = Notifications.addNotificationResponseReceivedListener(
(response) => {
const data = response.notification.request.content.data;
console.log('Tapped:', data);
}
);
// TODO: clean up subscriptions in the cleanup function (remove())
return () => {
notificationListener.current?.remove();
responseListener.current?.remove();
};
}, []);
return { lastNotification };
}
export default function App() {
const { lastNotification } = useNotifications();
return (
<View style={styles.container}>
<Text style={styles.title}>Push Notifications</Text>
<Text style={styles.info}>Last: {lastNotification || 'none'}</Text>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#1a5276' },
title: { fontSize: 24, color: '#fff', marginBottom: 12 },
info: { fontSize: 14, color: '#aed6f1' },
});
Docs entries used in this lesson
Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. What format does the Expo Push Token have?
2. To which URL do we send push via Expo?
These are 2 of 4 questions for this lesson. Solve the rest in the game.
Hands-on tasks in the game
- Vertical ordering
Arrange the push notification payload:
- Code editor
Complete the code with listeners.