Bird
Raised Fist0
React Nativemobile~20 mins

Push notifications (expo-notifications) in React Native - Mini App: Build & Ship

Choose your learning style10 modes available
Build: Push Notification Demo
This screen registers the device for push notifications using expo-notifications and shows the device token. It also listens for incoming notifications and displays their content.
Target UI
-------------------------
| Push Notification Demo |
-------------------------

Device Token:
[________________________]

Last Notification:
Title: 
Body: 

[Request Permission Button]
Request permission to send push notifications when user taps the button
Get and display the Expo push token after permission is granted
Listen for incoming notifications and display their title and body on screen
Use expo-notifications package for all notification handling
Starter Code
React Native
import React, { useState, useEffect, useRef } from 'react';
import { View, Text, Button, ScrollView } from 'react-native';
import * as Notifications from 'expo-notifications';
import Constants from 'expo-constants';

export default function PushNotificationDemo() {
  const [expoPushToken, setExpoPushToken] = useState('');
  const [notification, setNotification] = useState(false);
  const notificationListener = useRef();
  const responseListener = useRef();

  useEffect(() => {
    // TODO: Add notification listeners here

    return () => {
      // TODO: Remove notification listeners here
    };
  }, []);

  async function registerForPushNotificationsAsync() {
    // TODO: Request permissions and get token
  }

  return (
    <ScrollView contentContainerStyle={{ padding: 20 }}>
      <Text style={{ fontSize: 20, fontWeight: 'bold', marginBottom: 10 }}>Push Notification Demo</Text>
      <Text style={{ marginBottom: 5 }}>Device Token:</Text>
      <Text selectable style={{ marginBottom: 20 }}>{expoPushToken || 'No token yet'}</Text>

      <Text style={{ marginBottom: 5 }}>Last Notification:</Text>
      <Text>Title: {notification ? notification.request.content.title : ''}</Text>
      <Text>Body: {notification ? notification.request.content.body : ''}</Text>

      <View style={{ marginTop: 30 }}>
        <Button title="Request Permission" onPress={registerForPushNotificationsAsync} />
      </View>
    </ScrollView>
  );
}
Task 1
Task 2
Task 3
Solution
React Native
import React, { useState, useEffect, useRef } from 'react';
import { View, Text, Button, ScrollView, Platform } from 'react-native';
import * as Notifications from 'expo-notifications';
import Constants from 'expo-constants';

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

export default function PushNotificationDemo() {
  const [expoPushToken, setExpoPushToken] = useState('');
  const [notification, setNotification] = useState(null);
  const notificationListener = useRef();
  const responseListener = useRef();

  useEffect(() => {
    // Listener called when a notification is received while app is foreground
    notificationListener.current = Notifications.addNotificationReceivedListener(notification => {
      setNotification(notification);
    });

    // Listener called when user interacts with a notification
    responseListener.current = Notifications.addNotificationResponseReceivedListener(response => {
      // Could handle response here if needed
    });

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

  async function registerForPushNotificationsAsync() {
    let token;
    if (!Constants.isDevice) {
      alert('Must use physical device for Push Notifications');
      return;
    }
    const { status: existingStatus } = await Notifications.getPermissionsAsync();
    let finalStatus = existingStatus;
    if (existingStatus !== 'granted') {
      const { status } = await Notifications.requestPermissionsAsync();
      finalStatus = status;
    }
    if (finalStatus !== 'granted') {
      alert('Failed to get push token for push notification!');
      return;
    }
    token = (await Notifications.getExpoPushTokenAsync()).data;
    setExpoPushToken(token);

    if (Platform.OS === 'android') {
      Notifications.setNotificationChannelAsync('default', {
        name: 'default',
        importance: Notifications.AndroidImportance.MAX,
        vibrationPattern: [0, 250, 250, 250],
        lightColor: '#FF231F7C',
      });
    }
  }

  return (
    <ScrollView contentContainerStyle={{ padding: 20 }}>
      <Text style={{ fontSize: 20, fontWeight: 'bold', marginBottom: 10 }}>Push Notification Demo</Text>
      <Text style={{ marginBottom: 5 }}>Device Token:</Text>
      <Text selectable style={{ marginBottom: 20 }}>{expoPushToken || 'No token yet'}</Text>

      <Text style={{ marginBottom: 5 }}>Last Notification:</Text>
      <Text>Title: {notification ? notification.request.content.title : ''}</Text>
      <Text>Body: {notification ? notification.request.content.body : ''}</Text>

      <View style={{ marginTop: 30 }}>
        <Button title="Request Permission" onPress={registerForPushNotificationsAsync} />
      </View>
    </ScrollView>
  );
}

This app screen uses the expo-notifications package to handle push notifications.

When the user taps the "Request Permission" button, the app asks for permission to send notifications. If granted, it fetches the Expo push token and shows it on screen.

The app also sets up listeners to detect when a notification arrives while the app is open (foreground). It updates the screen to show the notification's title and body.

On Android, it creates a notification channel for proper notification behavior.

This setup helps you test push notifications and see the device token needed to send notifications from a server or Expo push service.

Final Result
Completed Screen
-------------------------
| Push Notification Demo |
-------------------------

Device Token:
ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]

Last Notification:
Title: Hello
Body: This is a test notification

[Request Permission Button]
User taps 'Request Permission' button to allow notifications and get device token
When a push notification arrives while app is open, the title and body appear under 'Last Notification'
Stretch Goal
Add a button to send a test local notification immediately
💡 Hint
Use Notifications.scheduleNotificationAsync with trigger: null to show a notification right away

Practice

(1/5)
1. What is the main purpose of using expo-notifications in a React Native app?
easy
A. To create animations for app screens
B. To send and receive push notifications to keep users informed
C. To manage app navigation between screens
D. To handle user authentication and login

Solution

  1. Step 1: Understand the role of expo-notifications

    The expo-notifications library is designed to handle push notifications in React Native apps.
  2. Step 2: Identify the correct purpose

    It allows apps to send and receive notifications, keeping users informed even when the app is closed.
  3. Final Answer:

    To send and receive push notifications to keep users informed -> Option B
  4. Quick Check:

    expo-notifications = Push notifications [OK]
Hint: Remember: expo-notifications is for alerts, not UI or auth [OK]
Common Mistakes:
  • Confusing notifications with navigation or animations
  • Thinking expo-notifications manages user login
  • Assuming it handles UI styling
2. Which of the following is the correct way to request notification permissions using expo-notifications?
easy
A. await Notifications.requestPermissionsAsync();
B. Notifications.getPermissions();
C. await Notifications.askForPermissions();
D. Notifications.permissionRequest();

Solution

  1. Step 1: Recall the correct method name

    The official method to request permissions is requestPermissionsAsync() from expo-notifications.
  2. Step 2: Check syntax correctness

    The method is asynchronous and should be awaited: await Notifications.requestPermissionsAsync();
  3. Final Answer:

    await Notifications.requestPermissionsAsync(); -> Option A
  4. Quick Check:

    Permission request method = requestPermissionsAsync [OK]
Hint: Look for async method starting with 'request' [OK]
Common Mistakes:
  • Using non-existent methods like getPermissions or askForPermissions
  • Forgetting to await the async call
  • Using incorrect method names
3. Given the code snippet below, what will be logged when a notification is received?
import * as Notifications from 'expo-notifications';

Notifications.addNotificationReceivedListener(notification => {
  console.log(notification.request.content.title);
});

// Assume a notification with title 'Hello User' arrives
medium
A. undefined
B. notification
C. Hello User
D. Error: notification is not defined

Solution

  1. Step 1: Understand the listener callback

    The listener receives a notification object, and logs notification.request.content.title.
  2. Step 2: Match the notification content

    The notification has a title 'Hello User', so that string will be logged.
  3. Final Answer:

    Hello User -> Option C
  4. Quick Check:

    Logged title = 'Hello User' [OK]
Hint: Listener logs notification title property [OK]
Common Mistakes:
  • Expecting the whole notification object to be logged
  • Confusing property names or missing nested fields
  • Assuming undefined if not familiar with notification structure
4. What is wrong with this code snippet for getting the push token?
import * as Notifications from 'expo-notifications';

const getToken = async () => {
  const token = Notifications.getExpoPushTokenAsync();
  console.log(token);
};

getToken();
medium
A. Missing await before Notifications.getExpoPushTokenAsync()
B. Wrong import statement for Notifications
C. console.log should be inside a .then() block
D. getToken function should not be async

Solution

  1. Step 1: Identify async function usage

    The method getExpoPushTokenAsync() returns a Promise and must be awaited.
  2. Step 2: Check the code for await

    The code calls Notifications.getExpoPushTokenAsync() without await, so token is a Promise, not the actual token.
  3. Final Answer:

    Missing await before Notifications.getExpoPushTokenAsync() -> Option A
  4. Quick Check:

    Async calls need await to get result [OK]
Hint: Always await async calls to get actual values [OK]
Common Mistakes:
  • Forgetting to await async functions
  • Misunderstanding Promises vs values
  • Incorrect import statements
  • Logging before Promise resolves
5. You want to send a push notification only when the user has granted permission. Which sequence of steps correctly implements this using expo-notifications?
hard
A. Send notification directly without requesting permission or token
B. Get token first with getExpoPushTokenAsync(), then request permission with requestPermissionsAsync()
C. Only request permission and send notification without getting token
D. Request permission with requestPermissionsAsync(), check status, then get token with getExpoPushTokenAsync() if granted

Solution

  1. Step 1: Request notification permission

    Use requestPermissionsAsync() to ask the user for permission and check the returned status.
  2. Step 2: Get push token if permission granted

    If permission is granted, call getExpoPushTokenAsync() to get the device token for sending notifications.
  3. Step 3: Send notification using the token

    Use the token to send push notifications from your server or app.
  4. Final Answer:

    Request permission with requestPermissionsAsync(), check status, then get token with getExpoPushTokenAsync() if granted -> Option D
  5. Quick Check:

    Permission first, then token, then send [OK]
Hint: Always request permission before getting token [OK]
Common Mistakes:
  • Getting token before permission
  • Sending notifications without token
  • Skipping permission check
  • Assuming permission is granted by default
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard