zo0r / react-native-push-notification

React Native Local and Remote Notifications
MIT License
6.75k stars 2.05k forks source link

Redirect to specific screen when `configure()`is outside a React component #2056

Open thomasviaud opened 3 years ago

thomasviaud commented 3 years ago

Hi,

I've read that writing the PushNotification.configure()outside any React component is required.

In my case I'm receiving remote notifications from an external service (GetStream chat https://getstream.io/chat/docs/react-native/push_template/?language=javascript). I'd like to redirect the user that clicks on the notification to a specific chat screen. How can I achieve that in iOS and Android since I don't have access to the React router in my onNotification() function. Should I handle this in Java and Swift directly ?

I've tried to find related issues and answers, but can't find a clear way of doing.

Thanks.

Dallas62 commented 3 years ago

Hi,

Put the notification or the router in a global variable and redirect when you can. useEffect that read the notification stored, or call the redirection with the global variable of the router.

Regards

thomasviaud commented 3 years ago

Hi thanks.

I did not manage to do the trick with global variables since I'm not getting updates when the global variable is updated (react world vs javascript world).

I found a solution with an event based mechanism (feel free to challenge it). I'm posting it here for people having to solve this problem :

// Pending notifications
const pendingNotifications = [];

notificationEventEmitter.once('newListener', (event) => {
  if (event === NotificationType.ClickedNotification) {
    pendingNotifications.forEach((item) => {
      // Need to wait next tick otherwise event will be lost cause listener is not ready yet.
      process.nextTick(() => {
        notificationEventEmitter.emit(
          NotificationType.ClickedNotification,
          item,
        );
      });
    });
  }
});

// Push notification configuration (must be outside of any React component)
PushNotification.configure({
  onRegister(token) {
    // Do some stuff here
  },
  onNotification(notification) {
    logger.info(`Received notification : ${JSON.stringify(notification)}`);

    if (
      notificationEventEmitter.listenerCount(
        NotificationType.ClickedNotification,
      ) > 0
    ) {
      logger.info('Listener ready. Emitting event...');
      notificationEventEmitter.emit(
        NotificationType.ClickedNotification,
        notification,
      );
    } else {
      logger.info(
        'Listener not yet initialized. Storing notification temporarly.',
      );
      pendingNotifications.push(notification);
    }

    notification.finish(PushNotificationIOS.FetchResult.NoData);
  },
  onRegistrationError(err) {
    logger.error(err);
  },
  popInitialNotification: true,
  requestPermissions: true,
});

And you can listen to emitted events in your react component :

// Somewhere in your React app, where Router is available
// Redirect to screen if user is coming from a notification.
  useEffect(() => {
    notificationEmitter.addListener(
      NotificationType.ClickedNotification,
      handleNotificationEvent,
    );

    return () => {
      notificationEmitter.removeListener(
        NotificationType.ClickedNotification,
        handleNotificationEvent,
      );
    };
  }, []);

  const handleNotificationEvent = (notification: ReceivedNotification) => {
    logger.info('Handling notification ...');
    // Replace with your own handling logic
    if (notification?.data?.channel) {
      const parsedChannelData = JSON.parse(notification.data.channel);
      navigation.navigate(Routes.Group, {
        groupId: parsedChannelData.id,
      });
    }
  };
Raymond-Cox commented 3 years ago

If you're using react navigation, I implemented it this way:

https://reactnavigation.org/docs/navigating-without-navigation-prop

github-actions[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 30 days if no further activity occurs. Thank you for your contributions.