Cours React Native · Module 7: Notifications

Projet : Système de notifications de l'Atlantide

2 min de lecture ·

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.

Articles utiles