deep link to app screens via notifications on Expo

Jul 1, 2023

continuing from setting up notifications using expo-notifications, assuming that we use React Navigation for routing and navigation in our Expo app, it’s pretty easy to direct the user to specific screens when they interact with a notification.

you must have a setup like below at the root of your app once you’ve done configuring the navigator with React Navigation:

import { NativeStackScreenProps, createNativeStackNavigator } from '@react-navigation/native-stack'
import { NavigationContainer } from '@react-navigation/native';
import { Home } from './Home';
import { User } from './User';

type StackParams = {
  'home': undefined;
  'user': { id: number };
  // ...
}

export HomeProps = NativeStackScreenProps<StackParams, 'home'>;
export UserProps = NativeStackScreenProps<StackParams, 'user'>;
// ...

const Stack = createNativeStackNavigator<StackParams>();

const App = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName='home'>
        <Stack.Screen
	  name='home'
	  component={Home}
	/>
	<Stack.Screen
	  name='user'
	  component={User}
	/>
	{
	  // rest of the screens
	}
      </Stack.Navigator>
    </NavigationContainer>
  );
}

we can start by constructing the JSON payload that we send with a notification, so it holds a route name and route parameters if any.

{
  to: pushToken,
  title: 'notification title',
  body: 'notification body',
  data: { screen: 'user', params: { id: 4 } },
}

somewhere preferably close to the app root and within the NavigationContainer, we can use the useLastNotificationResponse hook to retrieve the notification response that was received most recently and access the data object.

using the useNavigation hook we can navigate to the screen like below whenever we detect interaction with a notification:

import { useNavigation } from '@react-navigation/native';
import * as Notifications from 'expo-notifications';

const navigation = useNavigation();

const response = Notifications.useLastNotificationResponse();

useEffect(() => {
  if (response) {
    const { content: { data: { screen, params } } } = response.notification.request;

    if (screen) {
      navigation.navigate(screen, params ? params : undefined);
    }
  }
}, [response]);