Cours React Native · Module 7: Notifications
Projet : Système de notifications de l'Atlantide
Créons un système de notifications complet !
import { useEffect, useRef, useState } from 'react';
import * as Notifications from 'expo-notifications';
import * as Device from 'expo-device';
import { Platform } from 'react-native';
// Configuration
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowBanner: true,
shouldShowList: true,
shouldPlaySound: true,
shouldSetBadge: true,
}),
});
// Hook des notifications
export function useNotifications() {
const [expoPushToken, setExpoPushToken] = useState<string>('');
const [notification, setNotification] = useState<Notifications.Notification>();
const notificationListener = useRef<Notifications.Subscription>();
const responseListener = useRef<Notifications.Subscription>();
useEffect(() => {
// Enregistrement
registerForPushNotificationsAsync().then((token) => {
if (token) setExpoPushToken(token);
});
// Configuration des canaux Android
setupAndroidChannels();
// Listeners
notificationListener.current = Notifications.addNotificationReceivedListener(
setNotification
);
responseListener.current = Notifications.addNotificationResponseReceivedListener(
(response) => {
handleNotificationResponse(response);
}
);
return () => {
notificationListener.current?.remove();
responseListener.current?.remove();
};
}, []);
return { expoPushToken, notification };
}
async function registerForPushNotificationsAsync() {
if (!Device.isDevice) {
console.log('Les notifications push nécessitent un appareil');
return;
}
const { status: existingStatus } = await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== 'granted') {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== 'granted') {
return;
}
const token = await Notifications.getExpoPushTokenAsync();
return token.data;
}
async function setupAndroidChannels() {
if (Platform.OS !== 'android') return;
await Notifications.setNotificationChannelAsync('default', {
name: 'Default',
importance: Notifications.AndroidImportance.MAX,
});
await Notifications.setNotificationChannelAsync('reminders', {
name: 'Reminders',
importance: Notifications.AndroidImportance.HIGH,
});
}
function handleNotificationResponse(response: Notifications.NotificationResponse) {
const data = response.notification.request.content.data;
// Naviguer en fonction des données
console.log('Données de la notification :', data);
}
// Services de notification
export const NotificationService = {
// Notification locale
sendLocal: async (title: string, body: string, data?: object) => {
return Notifications.scheduleNotificationAsync({
content: { title, body, data, sound: true },
trigger: null,
});
},
// Rappel
scheduleReminder: async (title: string, body: string, date: Date) => {
return Notifications.scheduleNotificationAsync({
content: { title, body },
trigger: date,
});
},
// Rappel quotidien
scheduleDailyReminder: async (title: string, body: string, hour: number, minute: number) => {
return Notifications.scheduleNotificationAsync({
content: { title, body },
trigger: { hour, minute, repeats: true },
});
},
// Tout annuler
cancelAll: async () => {
await Notifications.cancelAllScheduledNotificationsAsync();
},
// Effacer le badge
clearBadge: async () => {
await Notifications.setBadgeCountAsync(0);
},
};Ce système gère l'enregistrement, les notifications locales, les notifications push et les canaux Android !
Code de cette leçon : App.tsx
import { View, Text, Button, StyleSheet } from 'react-native';
import * as Notifications from 'expo-notifications';
// Projet : service de notifications complet pour l'Atlantide
export const NotificationService = {
// Notification locale immédiate
sendLocal: async (title: string, body: string, data?: object) => {
// TODO : appelle scheduleNotificationAsync avec trigger: null
return Notifications.scheduleNotificationAsync({
content: { title, body, data, sound: true },
trigger: null,
});
},
// Rappel à une date précise
scheduleReminder: async (title: string, body: string, date: Date) => {
// TODO : définis trigger à la date transmise
return Notifications.scheduleNotificationAsync({
content: { title, body },
trigger: date,
});
},
// Rappel quotidien à une heure donnée
scheduleDailyReminder: async (title: string, body: string, hour: number, minute: number) => {
// TODO : définis trigger à { hour, minute, repeats: true }
return Notifications.scheduleNotificationAsync({
content: { title, body },
// TODO : complète le trigger avec repeats: true
trigger: { hour, minute, repeats: false },
});
},
// Annule toutes les notifications planifiées
cancelAll: async () => {
// TODO : appelle cancelAllScheduledNotificationsAsync()
},
// Efface le badge de l'icône de l'application
clearBadge: async () => {
// TODO : définis le badge à 0 avec setBadgeCountAsync(0)
},
};
export default function App() {
return (
<View style={styles.container}>
<Text style={styles.title}>Système de Notifications de l'Atlantide</Text>
<Button
title="Envoyer en local"
onPress={() => NotificationService.sendLocal('Atlantide', 'Poséidon te convoque !')}
/>
<Button title="Effacer le badge" onPress={NotificationService.clearBadge} />
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#1a5276', gap: 16, padding: 20 },
title: { fontSize: 22, color: '#fff', textAlign: 'center' },
});
Entrées de la documentation utilisées dans cette leçon
Tu as repéré une erreur dans cette leçon ?
Tâches pratiques dans le jeu
- Éditeur de code
Complète le code du service complet.