Leo S
Leo S

Reputation: 339

Do not show notification for one screen React Native

I have coded a chat app and I want to prevent the displaying of push notification in some screen for example when 2 users are chatting in the same room, the notification not showed to these 2 users but when someone leaves from the chat screen the user that left get a push notification but the user that stayed in chat screen not get a notification. I am new to React Native and Expo Notification services and I do not know how can I do that?

Note: I can detect which screen am I on. But I do not know how can I hide( For example, we can think 2 users A and B, and 2 chat rooms X and Y if user A and user B talked with each other in room X then these two user shouldn't receive push notification but when A leaves the room and B still in room X then just user A should receive push notification and user B souldn't receive notification) the received push notification for specific screen.

Code for try it works fine but throws lots of same notification and not stop until app crashed:

  const notificationListener = useRef();
  useEffect(() => {
    notificationListener.current = Notifications.addNotificationReceivedListener(
      (notification) => {
        // This is how you can get the data from the received notification
        const {
          room_id,
          message_text,
          type,
        } = notification.request.content.data;

        // If we receive a push notification which is not a new message,
        // we don't want to display a foreground push notification
        // if (type !== "NEW_MESSAGE") {
     
        //   return;
        // }
        if (room_id === 123) {
          console.log("trial");
          return;
        }

        Notifications.scheduleNotificationAsync({
          trigger: null,
          content: {
            title: "A new message",
            body: message_text,
          },
        });
      }
    );

    return () => {
      // Unsubscribe when component unmmounts
      Notifications.removeNotificationSubscription(
        notificationListener.current
      );
    };
  }, []);

Upvotes: 1

Views: 2023

Answers (1)

Kapobajza
Kapobajza

Reputation: 2459

According to the Expo push notification docs the Notifications.addNotificationReceivedListener listener could be used in your case. You can subscribe to this listener inside of your chat room screen and unsubscribe when the component unmounts. Furthermore you can check inside of the subscription if the received notification is targeting the chat room screen that the user is currently on. Here's an example:

I assume that you receive a push notification with the following data in the payload:

{
  room_id: 1,
  type: "NEW_MESSAGE"
}

This is how your chat room screen could look like:

import * as Notifications from 'expo-notifications';

const ChatRoomScreen = ({ roomId }) => {
  useEffect(() => {
    // This listener is fired whenever a notification is received while the app is foregrounded
    notificationListener.current = Notifications.addNotificationReceivedListener((notification) => {
      // This is how you can get the data from the received notification
      const { room_id, message_text, type } = notification?.request?.content?.data ?? {};

      // If we receive a push notification which is not a new message,
      // we don't want to display a foreground push notification
      if (type !== 'NEW_MESSAGE') {
        return;
      }

      // If the user is currently on this screen and the
      // room_id from the push notification is the same as on this screen (in other words the roomId prop),
      // we don't want to display a foreground push notification
      if (room_id === roomId) {
        return;
      }

      // Display a foreground notification here, since the push notification is targeting another chat room
      Notifications.scheduleNotificationAsync({
        // We're setting the trigger to null since we want the notification to be presented immediately
        trigger: null,
        content: {
          title: 'A new message',
          body: message_text,
        },
      });
    });

    return () => {
      // Unsubscribe when component unmmounts
      Notifications.removeNotificationSubscription(notificationListener.current);
    };
  }, [roomId]);
};

Another way to do it is that you could have the current chat room id in your global state and then in the handleNotification callback you could check if the chat room id received in the notification is the same as the one in the global state. If it is, don't display the notification. You could update your Notifications.setNotificationHandler to something like this:

Notifications.setNotificationHandler({
  handleNotification: (n) => {
    const { room_id } = n?.request?.content?.data ?? {};
    // Get the room id from your global state, maybe from redux or similar
    const showNotification = room_id !== globalState.roomId;

    return new Promise((resolve) =>
      resolve({
        shouldShowAlert: showNotification,
        shouldPlaySound: false,
        shouldSetBadge: false,
      }),
    );
  },
});

Upvotes: 3

Related Questions