Push notification doesn't open specific screen when app is killed, works only in foreground and background

  1. SDK 41.
  2. Android / iOS
  3. expo-notifications

I have a problem where I need to redirect user to specific post when he taps on notification, but that only works when app is in foreground or background. I’m using addNotificationResponseRecievedListener in useEffect hook where I navigate to specific screen when I have a response. Can someone tell me what should I do to open specific screen when app is killed?

If it only works in the foreground or the background, you are either:

  • on an older SDK (<41) where this was a bug, or
  • you’re calling addNotificationResponseRecievedListener too late after startup of the app. It should be called as early as possible in your app’s startup
import { Ionicons } from '@expo/vector-icons'
import { NavigationContainer } from '@react-navigation/native'
import { createStackNavigator } from '@react-navigation/stack'
import AppLoading from 'expo-app-loading'
import * as Font from 'expo-font'
import * as Notifications from 'expo-notifications'
import React, { useEffect, useRef, useState } from 'react'
import { AsyncStorage } from 'react-native'
import { enableScreens } from 'react-native-screens'
import { Provider } from 'react-redux'
import configureStore from './configureStore'
import DrawerNavigation from './navigation/DrawerNavigation'
import rootReducer from './rootReducer'
import rootSaga from './saga/saga'
import PushNotificationsScreen from './src/screens/PushNotificationsScreen'

enableScreens()
const store = configureStore(rootReducer, rootSaga)

const Stack = createStackNavigator()

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

export default function App() {
 const [isAppLoading, setIsAppLoading] = useState(false)
 const [isFirstLaunch, setIsFirstLaunch] = useState(null)
 const notificationListener = useRef()
 const responseListener = useRef()
 const navigationRef = useRef()

 useEffect(() => {

 // This listener is fired whenever a notification is received while the app is foregrounded
 notificationListener.current = Notifications.addNotificationReceivedListener((notification) => {
 // console.log(notification)
 })

 // This listener is fired whenever a user taps on or interacts with a notification (works when app is foregrounded, backgrounded, or killed)
 responseListener.current = Notifications.addNotificationResponseReceivedListener((response) => {
 navigationRef.current?.navigate('Post', {
 id: response.notification.request.content.data.id,
 })
 })

 const fetchFonts = async () => {
 try {
 await Font.loadAsync({
 Roboto: require('native-base/Fonts/Roboto.ttf'),
 Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
 ...Ionicons.font,
 })
 } catch (error) {
 // console.log(error)
 Sentry.Native.captureException(new Error(error))
 }
 }
 fetchFonts()
 setIsAppLoading(true)

 // onboarding screen
 AsyncStorage.getItem('alreadyLaunched').then((value) => {
 if (value === null) {
 AsyncStorage.setItem('alreadyLaunched', 'true')
 setIsFirstLaunch(true)
 } else {
 setIsFirstLaunch(false)
 }
 })

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

 if (!isAppLoading) {
 return <AppLoading />
 }

 if (isFirstLaunch === null) {
 return null
 } else if (isFirstLaunch === true) {
 return (
 <Provider store={store}>
 <NavigationContainer>
 <Stack.Navigator
 screenOptions={{
 headerShown: false,
 }}
 initialRouteName="pushNotif"
 >
 <Stack.Screen name="myDrawer" component={DrawerNavigation} />
 <Stack.Screen name="pushNotif" component={PushNotificationsScreen} />
 </Stack.Navigator>
 </NavigationContainer>
 </Provider>
 )
 } else {
 return (
 <Provider store={store}>
 <NavigationContainer ref={navigationRef}>
 <Stack.Navigator
 screenOptions={{
 headerShown: false,
 }}
 >
 <Stack.Screen name="myDrawer" component={DrawerNavigation} />
 </Stack.Navigator>
 </NavigationContainer>
 </Provider>
 )
 }
}

I tried to put everywhere listener, but with no success, i will provide also package.json

{
 "main": "node_modules/expo/AppEntry.js",
 "scripts": {
 "start": "expo start",
 "android": "expo start --android",
 "ios": "expo start --ios",
 "web": "expo start --web",
 "eject": "expo eject",
 "lint": "eslint src",
 "pretty": "prettier --semi false --print-width 100 --single-quote --trailing-comma all --write \"src/**/*.js\"",
 "precommit": "lint-staged",
 "test:unit": "jest",
 "test": "npm run lint && jest",
 "commit": "git-cz",
 "debug": "rndebugger-open --open React Native Debugger --port 19001"
 },
 "lint-staged": {
 "*.js": [
 "npm run pretty",
 "git add"
 ]
 },
 "jest": {
 "preset": "react-native",
 "testMatch": [
 "**/?(*.)test.js?(x)"
 ],
 "snapshotSerializers": [
 "enzyme-to-json/serializer"
 ],
 "setupFiles": [
 "<rootDir>/jest/setup.js"
 ]
 },
 "husky": {
 "hooks": {
 "pre-commit": "lint-staged",
 "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
 }
 },
 "config": {
 "commitizen": {
 "path": "cz-conventional-changelog"
 }
 },
 "dependencies": {
 "@expo/vector-icons": "^12.0.0",
 "@react-native-community/masked-view": "0.1.10",
 "@react-navigation/drawer": "^5.11.2",
 "@react-navigation/native": "^5.8.9",
 "@react-navigation/stack": "^5.12.6",
 "@unimodules/core": "~7.1.0",
 "axios": "^0.21.1",
 "date-fns": "^2.16.1",
 "entities": "^2.1.0",
 "expo": "^41.0.1",
 "expo-app-loading": "^1.0.1",
 "expo-constants": "~10.1.3",
 "expo-font": "~9.1.0",
 "expo-linking": "~2.2.3",
 "expo-notifications": "~0.11.6",
 "expo-status-bar": "~1.0.4",
 "expo-web-browser": "~9.1.0",
 "fiction-expo-restart": "^1.0.9",
 "htmlparser2-without-node-native": "^3.9.2",
 "lodash": "^4.17.20",
 "native-base": "^2.15.2",
 "react": "16.13.1",
 "react-error-boundary": "^3.1.0",
 "react-native": "https://github.com/expo/react-native/archive/sdk-41.0.0.tar.gz",
 "react-native-gesture-handler": "~1.10.2",
 "react-native-reanimated": "~2.1.0",
 "react-native-safe-area-context": "3.2.0",
 "react-native-screens": "~3.0.0",
 "react-native-skeleton-placeholder": "^3.0.4",
 "react-native-svg": "12.1.0",
 "react-native-web": "~0.13.12",
 "react-native-web-swiper": "^2.1.9",
 "react-native-webview": "11.2.3",
 "react-redux": "^7.2.2",
 "redux": "^4.0.5",
 "redux-devtools-extension": "^2.13.8",
 "redux-logger": "^3.0.6",
 "redux-saga": "^1.1.3",
 "sentry-expo": "^3.1.0",
 "uuid": "^3.4.0"
 },
 "devDependencies": {
 "@babel/core": "~7.9.0",
 "@commitlint/cli": "^9.1.1",
 "@commitlint/config-conventional": "^9.1.1",
 "@welldone-software/why-did-you-render": "^6.0.5",
 "babel-eslint": "^10.1.0",
 "babel-preset-expo": "8.3.0",
 "commitizen": "^4.1.2",
 "cz-conventional-changelog": "^3.2.0",
 "enzyme": "^3.11.0",
 "enzyme-adapter-react-16": "^1.15.2",
 "enzyme-to-json": "^3.5.0",
 "eslint": "^7.5.0",
 "eslint-config-airbnb": "^18.2.0",
 "eslint-plugin-import": "^2.22.0",
 "eslint-plugin-jsx-a11y": "^6.3.1",
 "eslint-plugin-react": "^7.20.3",
 "eslint-plugin-react-native": "^3.8.1",
 "husky": "^4.2.5",
 "lint-staged": "^10.2.11",
 "prettier": "^2.0.5",
 "react-native-debugger-open": "^0.3.25"
 },
 "private": true
}

Can you build your app using the code from the Snack example in the expo-notifications docs, and tell me if you have the same problem? I just tested this in this GitHub issue and can confirm it works: addNotificationResponseReceivedListener and useLastNotificationResponse not triggered for killed Standalone iOS and Android apps · Issue #13333 · expo/expo · GitHub

Thank you for reply Charlie, here is what I’m doing. I replaced my App.js with code from expo-notifications docs and I’m sending a notification from Push Notification Tool. When app is opened, notification is received and displayed, but when I close app and tap on notification, nothing happens, like there is no response. Here’s a video, thank you once again!

This is probably due to the fact that this is in development. If you build a standalone app, it should work as expected

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.