Wat zijn Notificaties?

Notificaties zijn berichten die gebruikers ontvangen, zelfs als de app niet open is. Er zijn twee soorten:

Soorten notificaties:

  • Lokale notificaties: Worden door de app zelf verstuurd (bijvoorbeeld een herinnering)
  • Push notificaties: Worden verstuurd vanaf een server (bijvoorbeeld een nieuw bericht)

Use cases:

  • Herinneringen (lokaal)
  • Nieuwe berichten (push)
  • Updates en nieuws (push)
  • Alarm klok (lokaal)
  • Timers en countdowns (lokaal)

Installatie

Installeer de Expo Notifications package:

npx expo install expo-notifications

Import

import * as Notifications from 'expo-notifications';

Notification Handler Configureren

Stel in hoe notificaties moeten worden getoond als de app open is:

import * as Notifications from 'expo-notifications';

// Configureer hoe notificaties worden getoond
Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,      // Toon de notificatie
    shouldPlaySound: true,      // Speel geluid af
    shouldSetBadge: false,      // Update badge nummer
  }),
});

Permissies Aanvragen

Voor notificaties heb je permissie van de gebruiker nodig.

Permissie Vragen

import { useState, useEffect } from 'react';
import { View, Pressable, Text, Platform, StyleSheet } from 'react-native';
import * as Notifications from 'expo-notifications';

export default function App() {
  const [permission, setPermission] = useState(null);

  useEffect(() => {
    requestPermission();
  }, []);

  const requestPermission = async () => {
    const { status } = await Notifications.requestPermissionsAsync();
    setPermission(status === 'granted');

    if (status !== 'granted') {
      alert('Notificatie permissie geweigerd!');
    }
  };

  return (
    <View style={styles.container}>
      <Text>
        Permissie: {permission ? '✅ Toegestaan' : '❌ Geweigerd'}
      </Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
});

Let op: Op Android krijg je automatisch permissie, maar op iOS moet de gebruiker expliciet toestemming geven!

Lokale Notificaties

Lokale notificaties worden direct door je app verstuurd.

Direct Notificatie Versturen

import { View, Pressable, Text, StyleSheet } from 'react-native';
import * as Notifications from 'expo-notifications';

export default function App() {
  const sendNotification = async () => {
    await Notifications.scheduleNotificationAsync({
      content: {
        title: "Je hebt een bericht! 📬",
        body: "Dit is een test notificatie",
        data: { data: 'goes here' },
      },
      trigger: null, // null = verstuur direct
    });
  };

  return (
    <View style={styles.container}>
      <Pressable style={styles.button} onPress={sendNotification}>
        <Text style={styles.buttonText}>Verstuur Notificatie</Text>
      </Pressable>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    padding: 20,
  },
  button: {
    backgroundColor: '#007AFF',
    padding: 15,
    borderRadius: 8,
    alignItems: 'center',
  },
  buttonText: {
    color: 'white',
    fontWeight: 'bold',
    fontSize: 16,
  },
});

Met Geluid en Acties

const sendAdvancedNotification = async () => {
  await Notifications.scheduleNotificationAsync({
    content: {
      title: "Nieuwe Opdracht 📝",
      body: "Je hebt een nieuwe taak ontvangen!",
      sound: 'default',
      badge: 1,
      data: { 
        taskId: 123,
        screen: 'TaskDetail' 
      },
    },
    trigger: null,
  });
};

Notificaties Plannen

Plan notificaties voor later met een trigger.

Na X Seconden

const scheduleNotification = async () => {
  await Notifications.scheduleNotificationAsync({
    content: {
      title: "Herinnering ⏰",
      body: "5 seconden zijn verstreken!",
    },
    trigger: {
      seconds: 5,
    },
  });
};

Dagelijkse Herinnering

const scheduleDailyNotification = async () => {
  await Notifications.scheduleNotificationAsync({
    content: {
      title: "Dagelijkse Herinnering 🌅",
      body: "Goedemorgen! Vergeet niet te oefenen.",
    },
    trigger: {
      hour: 9,
      minute: 0,
      repeats: true,
    },
  });
};

Specifieke Datum

const scheduleForDate = async () => {
  const trigger = new Date();
  trigger.setMinutes(trigger.getMinutes() + 1); // Over 1 minuut

  await Notifications.scheduleNotificationAsync({
    content: {
      title: "Geplande Notificatie 📅",
      body: "Deze notificatie was gepland!",
    },
    trigger: trigger,
  });
};

Wekelijkse Herinnering

const scheduleWeeklyNotification = async () => {
  await Notifications.scheduleNotificationAsync({
    content: {
      title: "Wekelijkse Check-in 📊",
      body: "Tijd om je voortgang te bekijken!",
    },
    trigger: {
      weekday: 1, // Maandag (1 = maandag, 7 = zondag)
      hour: 10,
      minute: 0,
      repeats: true,
    },
  });
};

Geplande Notificaties Annuleren

// Annuleer één notificatie
const notificationId = await Notifications.scheduleNotificationAsync({...});
await Notifications.cancelScheduledNotificationAsync(notificationId);

// Annuleer alle geplande notificaties
await Notifications.cancelAllScheduledNotificationsAsync();

Push Notificaties

Push notificaties worden verstuurd vanaf een server. Je hebt een Expo Push Token nodig.

Push Token Ophalen

import { useState, useEffect } from 'react';
import { View, Text, StyleSheet } from 'react-native';
import * as Notifications from 'expo-notifications';
import * as Device from 'expo-device';

export default function App() {
  const [expoPushToken, setExpoPushToken] = useState('');

  useEffect(() => {
    registerForPushNotificationsAsync();
  }, []);

  const registerForPushNotificationsAsync = async () => {
    let token;

    if (Device.isDevice) {
      const { status: existingStatus } = 
        await Notifications.getPermissionsAsync();
      
      let finalStatus = existingStatus;
      
      if (existingStatus !== 'granted') {
        const { status } = await Notifications.requestPermissionsAsync();
        finalStatus = status;
      }
      
      if (finalStatus !== 'granted') {
        alert('Permissie voor notificaties geweigerd!');
        return;
      }
      
      token = await Notifications.getExpoPushTokenAsync({
        projectId: 'your-project-id',
      });
      
      setExpoPushToken(token.data);
      console.log('Push Token:', token.data);
    } else {
      alert('Push notificaties werken alleen op echte apparaten!');
    }
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Push Token:</Text>
      <Text style={styles.token}>{expoPushToken}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    justifyContent: 'center',
  },
  title: {
    fontSize: 18,
    fontWeight: 'bold',
    marginBottom: 10,
  },
  token: {
    fontSize: 12,
    color: '#666',
  },
});

Push Notificatie Testen

Test push notificaties met de Expo Push Tool:

Via Expo Push Tool:

  1. Ga naar https://expo.dev/notifications
  2. Plak je Expo Push Token
  3. Vul titel en bericht in
  4. Klik op "Send a Notification"

Push Notificatie Versturen vanaf Server

// Voorbeeld met Node.js
const sendPushNotification = async (expoPushToken) => {
  const message = {
    to: expoPushToken,
    sound: 'default',
    title: 'Nieuw Bericht!',
    body: 'Je hebt een nieuw bericht ontvangen',
    data: { someData: 'goes here' },
  };

  await fetch('https://exp.host/--/api/v2/push/send', {
    method: 'POST',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(message),
  });
};

Notificaties Afhandelen

Reageer op notificaties als gebruikers erop klikken.

Notificatie Klik Afhandelen

import { useEffect, useRef } from 'react';
import { View, Text } from 'react-native';
import * as Notifications from 'expo-notifications';

export default function App() {
  const notificationListener = useRef();
  const responseListener = useRef();

  useEffect(() => {
    // Luister naar notificaties (app is open)
    notificationListener.current = 
      Notifications.addNotificationReceivedListener(notification => {
        console.log('Notificatie ontvangen:', notification);
      });

    // Luister naar notificatie klikken
    responseListener.current = 
      Notifications.addNotificationResponseReceivedListener(response => {
        console.log('Notificatie geklikt:', response);
        
        // Haal data uit notificatie
        const data = response.notification.request.content.data;
        
        // Navigeer naar scherm
        if (data.screen) {
          // router.push(data.screen);
        }
      });

    return () => {
      Notifications.removeNotificationSubscription(
        notificationListener.current
      );
      Notifications.removeNotificationSubscription(
        responseListener.current
      );
    };
  }, []);

  return (
    <View>
      <Text>Wachten op notificaties...</Text>
    </View>
  );
}

Navigeren na Notificatie Klik

import { useRouter } from 'expo-router';
import * as Notifications from 'expo-notifications';

export default function App() {
  const router = useRouter();

  useEffect(() => {
    const subscription = 
      Notifications.addNotificationResponseReceivedListener(response => {
        const data = response.notification.request.content.data;
        
        // Navigeer naar detail scherm
        if (data.taskId) {
          router.push(`/tasks/${data.taskId}`);
        }
      });

    return () => subscription.remove();
  }, []);

  return <View>...</View>;
}

Badge Nummer Updaten

// Zet badge nummer
await Notifications.setBadgeCountAsync(5);

// Verhoog badge nummer
const currentBadge = await Notifications.getBadgeCountAsync();
await Notifications.setBadgeCountAsync(currentBadge + 1);

// Reset badge nummer
await Notifications.setBadgeCountAsync(0);

Volledig Voorbeeld - Herinnering App

import { useState, useEffect } from 'react';
import { View, TextInput, Pressable, Text, FlatList, StyleSheet } from 'react-native';
import * as Notifications from 'expo-notifications';

// Configureer notification handler
Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: true,
    shouldSetBadge: false,
  }),
});

export default function ReminderApp() {
  const [text, setText] = useState('');
  const [reminders, setReminders] = useState([]);

  useEffect(() => {
    requestPermission();
  }, []);

  const requestPermission = async () => {
    const { status } = await Notifications.requestPermissionsAsync();
    if (status !== 'granted') {
      alert('Notificatie permissie nodig!');
    }
  };

  const addReminder = async () => {
    if (!text.trim()) return;

    // Plan notificatie over 5 seconden
    const notificationId = await Notifications.scheduleNotificationAsync({
      content: {
        title: "Herinnering ⏰",
        body: text,
        data: { id: Date.now() },
      },
      trigger: {
        seconds: 5,
      },
    });

    // Voeg toe aan lijst
    setReminders([
      ...reminders,
      { id: notificationId, text, time: 'Over 5 seconden' },
    ]);
    
    setText('');
  };

  const deleteReminder = async (id) => {
    // Annuleer notificatie
    await Notifications.cancelScheduledNotificationAsync(id);
    
    // Verwijder uit lijst
    setReminders(reminders.filter(r => r.id !== id));
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Herinneringen</Text>

      <View style={styles.inputContainer}>
        <TextInput
          style={styles.input}
          placeholder="Nieuwe herinnering..."
          value={text}
          onChangeText={setText}
        />
        <Pressable style={styles.addButton} onPress={addReminder}>
          <Text style={styles.addButtonText}>+</Text>
        </Pressable>
      </View>

      <FlatList
        data={reminders}
        keyExtractor={(item) => item.id}
        renderItem={({ item }) => (
          <View style={styles.reminderCard}>
            <View style={styles.reminderInfo}>
              <Text style={styles.reminderText}>{item.text}</Text>
              <Text style={styles.timeText}>{item.time}</Text>
            </View>
            <Pressable onPress={() => deleteReminder(item.id)}>
              <Text style={styles.deleteButton}>X</Text>
            </Pressable>
          </View>
        )}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    backgroundColor: '#f5f5f5',
  },
  title: {
    fontSize: 32,
    fontWeight: 'bold',
    marginBottom: 20,
  },
  inputContainer: {
    flexDirection: 'row',
    marginBottom: 20,
  },
  input: {
    flex: 1,
    borderWidth: 1,
    borderColor: '#ddd',
    padding: 12,
    borderRadius: 8,
    backgroundColor: 'white',
    marginRight: 10,
  },
  addButton: {
    backgroundColor: '#007AFF',
    width: 50,
    borderRadius: 8,
    justifyContent: 'center',
    alignItems: 'center',
  },
  addButtonText: {
    color: 'white',
    fontSize: 24,
    fontWeight: 'bold',
  },
  reminderCard: {
    flexDirection: 'row',
    backgroundColor: 'white',
    padding: 15,
    borderRadius: 8,
    marginBottom: 10,
    alignItems: 'center',
  },
  reminderInfo: {
    flex: 1,
  },
  reminderText: {
    fontSize: 16,
    marginBottom: 4,
  },
  timeText: {
    fontSize: 12,
    color: '#666',
  },
  deleteButton: {
    color: 'red',
    fontSize: 18,
    fontWeight: 'bold',
    padding: 5,
  },
});

Samenvatting

Lokale Notificaties

Door app verstuurd

Push Notificaties

Via server verstuurd

Scheduling

Notificaties plannen

Handlers

Reageren op klikken

Je hebt nu geleerd:

  • Permissies aanvragen voor notificaties
  • Lokale notificaties direct versturen
  • Notificaties plannen met triggers
  • Push tokens ophalen voor remote notificaties
  • Notificatie klikken afhandelen
  • Complete herinnering app implementeren