This commit adds a new optional property on the `route` object called `path`.
This property will be added if the screen was opened from a deep link.
Having this property helps with few things:
- Preserve the URL when the path was unmatched, e.g. 404 routes
- Expose the path to the user so they could handle it manually if needed, e.g. open in a webview
- Avoid changing URL if state to path doesn't match current path, e.g. if orders of params change
Fixes#9102
BREAKING CHANGE: Returning to first route after pressing back seems more common in apps. This commit changes the default for tab and drawer navigators to follow this common practice. To preserve previous behavior, you can pass backBehavior=history to tab and drawer navigators.
For apps with push notifications linking to screens inside the app, currently we need to handle them separately (e.g. [instructions for firebase](https://rnfirebase.io/messaging/notifications#handling-interaction), [instructions for expo notifications](https://docs.expo.io/push-notifications/receiving-notifications/)). But if we add a link in the notification to use for deep linking, we can instead reuse the same deep linking logic instead.
This commit adds the `getInitialURL` and `subscribe` options which internally used `Linking` API to allow more advanced implementations by combining it with other sources such as push notifications.
Example usage with Firebase notifications could look like this:
```js
const linking = {
prefixes: ['myapp://', 'https://myapp.com'],
async getInitialURL() {
// Check if app was opened from a deep link
const url = await Linking.getInitialURL();
if (url != null) {
return url;
}
// Check if there is an initial firebase notification
const message = await messaging().getInitialNotification();
// Get the `url` property from the notification which corresponds to a screen
// This property needs to be set on the notification payload when sending it
return message?.notification.url;
},
subscribe(listener) {
const onReceiveURL = ({ url }: { url: string }) => listener(url);
// Listen to incoming links from deep linking
Linking.addEventListener('url', onReceiveURL);
// Listen to firebase push notifications
const unsubscribeNotification = messaging().onNotificationOpenedApp(
(message) => {
const url = message.notification.url;
if (url) {
// If the notification has a `url` property, use it for linking
listener(url);
}
}
);
return () => {
// Clean up the event listeners
Linking.removeEventListener('url', onReceiveURL);
unsubscribeNotification();
};
},
config,
};
```
Currently when we receive a deep link after the app is rendered, it always results in a `navigate` action. While it's ok with the default configuration, it may result in incorrect behaviour when a custom `getStateForPath` function is provided and it returns a routes array different than the initial route and new route pair.
The commit changes 2 things:
1. Add ability to reset state via params of `navigate` by specifying a `state` property instead of `screen`
2. Update `getStateForAction` to return an action for reset when necessary according to the deep linking configuration
Closes#8952
Prefixes should be more flexible for situations like wild card subdomain. On android and IOS we can define wild cards by * but react-navigation does not work, In this PR I added support for RegExp Prefixes.
For Example
```js
{
prefixes: [
/^[^.s]+.example.com/g
],
}
```
I tested this work well.
Closes#8941
Co-authored-by: Satyajit Sahoo <satyajit.happy@gmail.com>