Skip to content

Commit 2c6905e

Browse files
docs(messaging): update notification example for react-navigation v6 (#7439)
* Update notifications.md You cannot use `useNavigation` hooks from outside of `NavigationContainer` The properly way is to implement `linking` props of `NavigationContainer`. Reference document: https://reactnavigation.org/docs/navigation-container#linkingsubscribe * Reduce the example codebase Remove PostScreen component to simplify the codebase * Update docs/messaging/notifications.md --------- Co-authored-by: Mike Hardy <[email protected]>
1 parent e488c5c commit 2c6905e

File tree

1 file changed

+66
-37
lines changed

1 file changed

+66
-37
lines changed

docs/messaging/notifications.md

Lines changed: 66 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -112,61 +112,90 @@ we can set an initial route when the app is opened from a quit state, and push t
112112

113113
```jsx
114114
import React, { useState, useEffect } from 'react';
115+
import { Linking, ActivityIndicator } from 'react-native';
115116
import messaging from '@react-native-firebase/messaging';
116117
import { NavigationContainer, useNavigation } from '@react-navigation/native';
117118
import { createStackNavigator } from '@react-navigation/stack';
118119

119120
const Stack = createStackNavigator();
121+
const NAVIGATION_IDS = ['home', 'post', 'settings'];
120122

121-
function App() {
122-
const navigation = useNavigation();
123-
const [loading, setLoading] = useState(true);
124-
const [initialRoute, setInitialRoute] = useState('Home');
125-
126-
useEffect(() => {
127-
// Assume a message-notification contains a "type" property in the data payload of the screen to open
128-
129-
messaging().onNotificationOpenedApp(remoteMessage => {
130-
console.log(
131-
'Notification caused app to open from background state:',
132-
remoteMessage.notification,
133-
);
134-
navigation.navigate(remoteMessage.data.type);
135-
});
136-
137-
// Check whether an initial notification is available
138-
messaging()
139-
.getInitialNotification()
140-
.then(remoteMessage => {
141-
if (remoteMessage) {
142-
console.log(
143-
'Notification caused app to open from quit state:',
144-
remoteMessage.notification,
145-
);
146-
setInitialRoute(remoteMessage.data.type); // e.g. "Settings"
147-
}
148-
setLoading(false);
149-
});
150-
}, []);
151-
152-
if (loading) {
123+
function buildDeepLinkFromNotificationData(data): string | null {
124+
const navigationId = data?.navigationId;
125+
if (!NAVIGATION_IDS.includes(navigationId)) {
126+
console.warn('Unverified navigationId', navigationId)
153127
return null;
154128
}
129+
if (navigationId === 'home') {
130+
return 'myapp://home';
131+
}
132+
if (navigationId === 'settings') {
133+
return 'myapp://settings';
134+
}
135+
const postId = data?.postId;
136+
if (typeof postId === 'string') {
137+
return `myapp://post/${postId}`
138+
}
139+
console.warn('Missing postId')
140+
return null
141+
}
142+
143+
const linking = {
144+
prefixes: ['myapp://'],
145+
config: {
146+
initialRouteName: 'Home',
147+
screens: {
148+
Home: 'home',
149+
Post: 'post/:id',
150+
Settings: 'settings'
151+
}
152+
},
153+
async getInitialURL() {
154+
const url = await Linking.getInitialURL();
155+
if (typeof url === 'string') {
156+
return url;
157+
}
158+
//getInitialNotification: When the application is opened from a quit state.
159+
const message = await messaging().getInitialNotification();
160+
const deeplinkURL = buildDeepLinkFromNotificationData(message?.data);
161+
if (typeof deeplinkURL === 'string') {
162+
return deeplinkURL;
163+
}
164+
},
165+
subscribe(listener: (url: string) => void) {
166+
const onReceiveURL = ({url}: {url: string}) => listener(url);
155167

168+
// Listen to incoming links from deep linking
169+
const linkingSubscription = Linking.addEventListener('url', onReceiveURL);
170+
171+
//onNotificationOpenedApp: When the application is running, but in the background.
172+
const unsubscribe = messaging().onNotificationOpenedApp(remoteMessage => {
173+
const url = buildDeepLinkFromNotificationData(remoteMessage.data)
174+
if (typeof url === 'string') {
175+
listener(url)
176+
}
177+
});
178+
179+
return () => {
180+
linkingSubscription.remove();
181+
unsubscribe();
182+
};
183+
},
184+
}
185+
186+
function App() {
156187
return (
157-
<NavigationContainer>
158-
<Stack.Navigator initialRouteName={initialRoute}>
188+
<NavigationContainer linking={linking} fallback={<ActivityIndicator animating />}>
189+
<Stack.Navigator>
159190
<Stack.Screen name="Home" component={HomeScreen} />
191+
<Stack.Screen name="Post" component={PostScreen} />
160192
<Stack.Screen name="Settings" component={SettingsScreen} />
161193
</Stack.Navigator>
162194
</NavigationContainer>
163195
);
164196
}
165197
```
166198
167-
The call to `getInitialNotification` should happen within a React lifecycle method after mounting (e.g. `componentDidMount` or `useEffect`).
168-
If it's called too soon (e.g. within a class constructor or global scope), the notification data may not be available.
169-
170199
**Quick Tip:** On `Android` you can test receiving remote notifications on the emulator but on `iOS` you will need to use a real device as the iOS simulator does not support receiving remote notifications.
171200
172201
# Getting a Device Token

0 commit comments

Comments
 (0)