From 18329307e98d3524a082bca428c713ce9725975a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrycja=20Kali=C5=84ska?= <59940332+patrycjakalinska@users.noreply.github.com> Date: Tue, 5 Mar 2024 09:43:29 +0100 Subject: [PATCH] Migrate 'Navigation events' examples to static API in v7 (#1330) * Add static examples * Remvoe dependencies, default and use useNavigation instead of prop * Navigation events cleanup --------- Co-authored-by: kacperkapusciak --- .../navigating-without-navigation-prop.md | 6 +- .../version-7.x/navigation-events.md | 240 +++++++++++++++++- 2 files changed, 239 insertions(+), 7 deletions(-) diff --git a/versioned_docs/version-7.x/navigating-without-navigation-prop.md b/versioned_docs/version-7.x/navigating-without-navigation-prop.md index 06677284389..88bcff29f42 100755 --- a/versioned_docs/version-7.x/navigating-without-navigation-prop.md +++ b/versioned_docs/version-7.x/navigating-without-navigation-prop.md @@ -128,8 +128,10 @@ function Settings({ route }) { } const RootStack = createNativeStackNavigator({ - Home: Home, - Settings: Settings, + screens: { + Home: Home, + Settings: Settings, + }, }); const Navigation = createStaticNavigation(RootStack); diff --git a/versioned_docs/version-7.x/navigation-events.md b/versioned_docs/version-7.x/navigation-events.md index b23f364a10d..85468cf877a 100644 --- a/versioned_docs/version-7.x/navigation-events.md +++ b/versioned_docs/version-7.x/navigation-events.md @@ -4,6 +4,9 @@ title: Navigation events sidebar_label: Navigation events --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + You can listen to various events emitted by React Navigation to get notified of certain events, and in some cases, override the default action. There are few core events such as `focus`, `blur` etc. (documented below) that work for every navigator, as well as navigator specific events that work only for certain navigators. Apart from the core events, each navigator can emit their own custom events. For example, stack navigator emits `transitionStart` and `transitionEnd` events, tab navigator emits `tabPress` event etc. You can find details about the events emitted on the individual navigator's documentation. @@ -55,24 +58,146 @@ const unsubscribe = navigation.addListener('tabPress', (e) => { Normally, you'd add an event listener in `React.useEffect` for function components. For example: - + + -```js -function Profile() { +```js name="navigation.addListener with focus" snack version=7 +import * as React from 'react'; +import { View, Text } from 'react-native'; +import { Button } from '@react-navigation/elements'; +import { + createStaticNavigation, + useNavigation, +} from '@react-navigation/native'; +import { createNativeStackNavigator } from '@react-navigation/native-stack'; + +function SettingsScreen() { + const navigation = useNavigation(); + + return ( + + Settings Screen + + + ); +} + +// codeblock-focus-start +function ProfileScreen() { const navigation = useNavigation(); React.useEffect(() => { const unsubscribe = navigation.addListener('focus', () => { - // do something + // Screen was focused }); + return unsubscribe; + }, [navigation]); + React.useEffect(() => { + const unsubscribe = navigation.addListener('blur', () => { + // Screen was unfocused + }); return unsubscribe; }, [navigation]); - return ; + // Rest of the component + // codeblock-focus-end + return ( + + Profile Screen + + + ); + // codeblock-focus-start +} +// codeblock-focus-end + +const SettingsStack = createNativeStackNavigator({ + screens: { + Settings: SettingsScreen, + Profile: ProfileScreen, + }, +}); + +const Navigation = createStaticNavigation(SettingsStack); + +export default function App() { + return ; } ``` + + + +```js name="navigation.addListener with focus" snack version=7 +import * as React from 'react'; +import { View, Text } from 'react-native'; +import { Button } from '@react-navigation/elements'; +import { NavigationContainer, useNavigation } from '@react-navigation/native'; +import { createNativeStackNavigator } from '@react-navigation/native-stack'; + +function SettingsScreen({ navigation }) { + return ( + + Settings Screen + + + ); +} + +// codeblock-focus-start +function ProfileScreen({ navigation }) { + React.useEffect(() => { + const unsubscribe = navigation.addListener('focus', () => { + // Screen was focused + }); + return unsubscribe; + }, [navigation]); + + React.useEffect(() => { + const unsubscribe = navigation.addListener('blur', () => { + // Screen was unfocused + }); + return unsubscribe; + }, [navigation]); + + // Rest of the component + // codeblock-focus-end + return ( + + Profile Screen + + + ); + // codeblock-focus-start +} +// codeblock-focus-end + +const SettingsStack = createNativeStackNavigator(); + +export default function App() { + return ( + + + + + + + ); +} +``` + + + + The `unsubscribe` function can be returned as the cleanup function in the effect. For class components, you can add the event in the `componentDidMount` lifecycle method and unsubscribe in `componentWillUnmount`: @@ -113,6 +238,28 @@ Sometimes you might want to add a listener from the component where you defined Example: + + + +```js +const Tab = createBottomTabNavigatior({ + screens: { + Chat: { + screen: Chat, + listeners: { + tabPress: (e) => { + // Prevent default action + e.preventDefault; + }, + }, + }, + }, +}); +``` + + + + ```js ``` + + + You can also pass a callback which returns the object with listeners. It'll receive `navigation` and `route` as the arguments. Example: + + + +```js +const Tab = createBottomTabNavigatior({ + screens: { + Chat: { + screen: Chat, + listeners: ({ navigation, route }) => ({ + tabPress: (e) => { + // Prevent default action + e.preventDefault; + + // Do something with the `navigation` object + navigation.navigate('AnotherPlace'); + }, + }), + }, + }, +}); +``` + + + ```js ``` + + + ### `screenListeners` prop on the navigator You can pass a prop named `screenListeners` to the navigator component, where you can specify listeners for events from all screens for this navigator. This can be useful if you want to listen to specific events regardless of the screen, or want to listen to common events such as `state` which is emitted to all screens. Example: + + + +```js +const Stack = createNativeStackNavigator({ + screenListeners: { + state: (e) => { + // Do something with the state + console.log('state changed', e.data); + }, + }, + screens: { + Home: HomeScreen, + Profile: ProfileScreen, + }, +}); +``` + + + + ```js ``` + + + Similar to `listeners`, you can also pass a function to `screenListeners`. The function will receive the [`navigation` object](navigation-object.md) and the [`route` object](route-object.md) for each screen. This can be useful if you need access to the `navigation` object. + + + +```js +const Tab = createBottomTabNavigatior({ + screenListeners: ({ navigation }) => ({ + state: (e) => { + // Do something with the state + console.log('state changed', e.data); + + // Do something with the `navigation` object + if (!navigation.canGoBack()) { + console.log("we're on the initial screen"); + } + }, + }), + screens: { + Home: HomeScreen, + Profile: ProfileScreen, + }, +}); +``` + + + + ```js ({ @@ -186,3 +413,6 @@ Similar to `listeners`, you can also pass a function to `screenListeners`. The f ``` + + +