4

I am using react-native-push-notification. I had the issue of notifications not being displayed when the app is in background/killed state, to which the solution in multiple forums and GitHub is that we initialize and configure push notification (PushNotification.configure()) in index.js Inside the PushNotification.configure() function, onNotification() is the function called when the Push Notification is clicked. On click, I want to navigate to a particular screen in the app, but that is not possible currently as there is no navigation prop available in index.js

Is there any way the navigation could be made possible ?

Fullmetal
  • 57
  • 1
  • 12
  • 1
    What navigation library are you using? Are you sure the one that you use doesn't support deep links/paths? If it does, just send the path as the URL, pass it to the navigation library and (assuming you configure things correctly) you're good to go as all handling/path resolution will be done automatically. (as a reference, `react-navigation` has it) – Can Poyrazoğlu Sep 08 '21 at 12:28
  • I tried the deep link option. When the app is in a killed state, and the push notification is clicked, the app launches with the Splash screen and then navigates to the intended screen. But, my splash also has some redirection logic, so due to this, multiple screens are navigated to in the process. What do you suggest in this? – Fullmetal Sep 09 '21 at 05:31
  • I actually had a very similar problem. Solved it by refactoring my app to pass the whole path parsing logic to navigation container. By using a wrapper that returns the correct navigation container based on redux state (logged in vs. not logged in in my case) I let the appropriate navigation container handle the links. – Can Poyrazoğlu Sep 09 '21 at 09:53
  • Is redux necessary for this solution? – Fullmetal Sep 09 '21 at 13:39
  • Nope, it was just my case. The idea is having _some kind of state_ (redux or otherwise), splitting navigation containers (e.g. non-logged in flow vs logged-in screens) passing data to appropriate navigation containers and also passing the linking logic to handle any links and route to the appropriate screen. – Can Poyrazoğlu Sep 10 '21 at 07:54

2 Answers2

3

This is what you can do. Firstly, you can initialize and export navigationRef from the file in which you've NavigationContainer.

// App.js
    
import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { navigationRef } from './RootNavigation';

export const navigationRef = React.createRef();

export function navigate(name, params) {
  navigationRef.current?.navigate(name, params);
}
    
export default function App() {
  return (
        <NavigationContainer ref={navigationRef}>{/* ... */}</NavigationContainer>
  );
}

then you can import it in which you've PushNotification.configure()

// notification-service.js

import PushNotification from 'react-native-push-notification';
import { navigationRef } from './App';

/* Your other code */

PushNotification.configure({
  onNotifications: (notification) => {
  
  // Now you'll have access to the navigation object's function here...

  }
})

You can get more clarity from the docs here: navigating-without-navigation-prop

Owais ul wara
  • 51
  • 1
  • 8
  • I dont think this will work bcz onNotification will be fired when a notification arrives and it will navigate without even clicking on the notiifcation – Sami Ullah Dec 19 '22 at 06:01
0

Try with React Native Firebase

Example:

import React, { useState, useEffect } from 'react';
import messaging from '@react-native-firebase/messaging';
import { NavigationContainer, useNavigation } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

const Stack = createStackNavigator();

function App() {
  const navigation = useNavigation();
  const [loading, setLoading] = useState(true);
  const [initialRoute, setInitialRoute] = useState('Home');

  useEffect(() => {
    // Assume a message-notification contains a "type" property in the data payload of the screen to open

    messaging().onNotificationOpenedApp(remoteMessage => {
      console.log(
        'Notification caused app to open from background state:',
        remoteMessage.notification,
      );
      navigation.navigate(remoteMessage.data.type);
    });

    // Check whether an initial notification is available
    messaging()
      .getInitialNotification()
      .then(remoteMessage => {
        if (remoteMessage) {
          console.log(
            'Notification caused app to open from quit state:',
            remoteMessage.notification,
          );
          setInitialRoute(remoteMessage.data.type); // e.g. "Settings"
        }
        setLoading(false);
      });
  }, []);

  if (loading) {
    return null;
  }

  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName={initialRoute}>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Settings" component={SettingsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
Bogdan Kyrychuk
  • 269
  • 3
  • 7
  • I'm trying the above but I am getting this error -> "Couldn't find a navigation object. is your components inside NavigationContainer?"; what is the best way to solve for this? – Luke Irvin Nov 08 '22 at 17:34