diff --git a/versioned_docs/version-7.x/navigation-object.md b/versioned_docs/version-7.x/navigation-object.md index 5b345e5d8e4..7cf17a4cc72 100755 --- a/versioned_docs/version-7.x/navigation-object.md +++ b/versioned_docs/version-7.x/navigation-object.md @@ -4,6 +4,9 @@ title: Navigation object reference sidebar_label: Navigation object --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + The `navigation` object contains various convenience functions that dispatch navigation actions. It looks like this: - `navigation` @@ -69,24 +72,135 @@ The `navigate` method lets us navigate to another screen in your app. It takes t - `name` - A destination name of the route that has been defined somewhere - `params` - Params to pass to the destination route. - + + -```js +```js name="Navigate method" snack version=7 dependencies=@react-navigation/elements +import * as React from 'react'; +import { View, Text } from 'react-native'; +import { Button } from '@react-navigation/elements'; +import { + useNavigation, + createStaticNavigation, +} from '@react-navigation/native'; +import { createNativeStackNavigator } from '@react-navigation/native-stack'; + +// codeblock-focus-start +function HomeScreen() { + const navigation = useNavigation(); + + return ( + + This is the home screen of the app + + + ); +} +// codeblock-focus-end + +function ProfileScreen({ route }) { + const navigation = useNavigation(); + + return ( + + Profile Screen + Friends: + {route.params.names[0]} + {route.params.names[1]} + {route.params.names[2]} + + + ); +} + +const Stack = createNativeStackNavigator({ + initialRouteName: 'Home', + screens: { + Home: HomeScreen, + Profile: ProfileScreen, + }, +}); + +const Navigation = createStaticNavigation(Stack); + +function App() { + return ; +} + +export default App; +``` + + + + +```js name="Navigate method" snack version=7 dependencies=@react-navigation/elements +import * as React from 'react'; +import { View, Text } from 'react-native'; +import { Button } from '@react-navigation/elements'; +import { NavigationContainer } from '@react-navigation/native'; +import { createNativeStackNavigator } from '@react-navigation/native-stack'; + +// codeblock-focus-start function HomeScreen({ navigation: { navigate } }) { return ( - + This is the home screen of the app + + ); +} +// codeblock-focus-end + +function ProfileScreen({ navigation, route }) { + return ( + + Profile Screen + Friends: + {route.params.names[0]} + {route.params.names[1]} + {route.params.names[2]} + ); } + +const Stack = createNativeStackNavigator(); + +function App() { + return ( + + + + + + + ); +} + +export default App; ``` + + + In a stack navigator ([stack](stack-navigator.md) or [native stack](native-stack-navigator.md)), calling `navigate` with a screen name will have the following behavior: - If you're already on a screen with the same name, it will update its params and not push a new screen. @@ -97,10 +211,33 @@ By default, the screen is identified by its name. But you can also customize it For example, say you have specified a `getId` prop for `Profile` screen: + + + +```js +const Tabs = createBottomTabNavigator({ + screens: { + Profile: { + screen: ProfileScreen, + getId: ({ params }) => params.userId, + }, + }, +}); +``` + + + + ```js - params.userId} /> + params.userId} +/> ``` + + Now, if you have a stack with the history `Home > Profile (userId: bob) > Settings` and you call `navigate(Profile, { userId: 'alice' })`, the resulting screens will be `Home > Profile (userId: bob) > Settings > Profile (userId: alice)` since it'll add a new `Profile` screen as no matching screen was found. ### `goBack` @@ -109,31 +246,365 @@ The `goBack` method lets us go back to the previous screen in the navigator. By default, `goBack` will go back from the screen that it is called from: - + + -```js -function ProfileScreen({ navigation: { goBack } }) { +```js name="Navigate method" snack version=7 dependencies=@react-navigation/elements +import * as React from 'react'; +import { View, Text } from 'react-native'; +import { Button } from '@react-navigation/elements'; +import { + useNavigation, + createStaticNavigation, +} from '@react-navigation/native'; +import { createNativeStackNavigator } from '@react-navigation/native-stack'; + +function HomeScreen() { + const navigation = useNavigation(); + + return ( + + This is the home screen of the app + + + ); +} + +// codeblock-focus-start +function ProfileScreen({ route }) { + const navigation = useNavigation(); + + return ( + + Profile Screen + Friends: + {route.params.names[0]} + {route.params.names[1]} + {route.params.names[2]} + // highlight-next-line + + + ); +} +// codeblock-focus-end + +const Stack = createNativeStackNavigator({ + initialRouteName: 'Home', + screens: { + Home: HomeScreen, + Profile: ProfileScreen, + }, +}); + +const Navigation = createStaticNavigation(Stack); + +function App() { + return ; +} + +export default App; +``` + + + + +```js name="Navigate method" snack version=7 dependencies=@react-navigation/elements +import * as React from 'react'; +import { View, Text } from 'react-native'; +import { Button } from '@react-navigation/elements'; +import { NavigationContainer } from '@react-navigation/native'; +import { createNativeStackNavigator } from '@react-navigation/native-stack'; + +function HomeScreen({ navigation: { navigate } }) { + return ( + + This is the home screen of the app + + + ); +} + +// codeblock-focus-start +function ProfileScreen({ navigation, route }) { return ( - - ); } +// codeblock-focus-end + +const Stack = createNativeStackNavigator(); + +function App() { + return ( + + + + + + + ); +} + +export default App; ``` + + + ### `reset` The `reset` method lets us replace the navigator state with a new state: - + + -```js -navigation.reset({ - index: 0, - routes: [{ name: 'Profile' }], +```js name="Navigate - replace and reset" snack version=7 dependencies=@react-navigation/elements +import * as React from 'react'; +import { Button } from '@react-navigation/elements'; +import { View, Text } from 'react-native'; +import { + useNavigation, + createStaticNavigation, +} from '@react-navigation/native'; +import { createNativeStackNavigator } from '@react-navigation/native-stack'; + +function HomeScreen() { + const navigation = useNavigation(); + + return ( + + This is the home screen of the app + + + ); +} + +function ProfileScreen({ route }) { + const navigation = useNavigation(); + + return ( + + Profile Screen + Friends: + {route.params.names[0]} + {route.params.names[1]} + {route.params.names[2]} + + + + + + + ); +} + +function SettingsScreen({ route }) { + const navigation = useNavigation(); + + return ( + + Settings screen + {route.params.someParam} + + + + ); +} + +const Stack = createNativeStackNavigator({ + initialRouteName: 'Home', + screens: { + Home: HomeScreen, + Profile: ProfileScreen, + Settings: SettingsScreen, + }, }); + +const Navigation = createStaticNavigation(Stack); + +function App() { + return ; +} + +export default App; ``` + + + +```js name="Navigate - replace and reset" snack version=7 dependencies=@react-navigation/elements +import * as React from 'react'; +import { Button } from '@react-navigation/elements'; +import { View, Text } from 'react-native'; +import { NavigationContainer } from '@react-navigation/native'; +import { createNativeStackNavigator } from '@react-navigation/native-stack'; + +function HomeScreen({ navigation: { navigate } }) { + return ( + + This is the home screen of the app + + + ); +} + +function ProfileScreen({ navigation, route }) { + return ( + + Profile Screen + Friends: + {route.params.names[0]} + {route.params.names[1]} + {route.params.names[2]} + + + + + + + ); +} + +function SettingsScreen({ navigation, route }) { + return ( + + Settings screen + {route.params.someParam} + + + + ); +} + +const Stack = createNativeStackNavigator(); + +function App() { + return ( + + + + + + + + ); +} + +export default App; +``` + + + + The state object specified in `reset` replaces the existing [navigation state](navigation-state.md) with the new one, i.e. removes existing screens and add new ones. If you want to preserve the existing screens when changing the state, you can use [`CommonActions.reset`](navigation-actions.md#reset) with [`dispatch`](#dispatch) instead. :::warning @@ -146,44 +617,289 @@ Consider the navigator's state object to be internal and subject to change in a The `setParams` method lets us update the params (`route.params`) of the current screen. `setParams` works like React's `setState` - it shallow merges the provided params object with the current params. - + + -```js -function ProfileScreen({ navigation: { setParams } }) { - return ( - + + ); +} + +// codeblock-focus-start +function ProfileScreen({ route }) { + const navigation = useNavigation(); + + return ( + + Profile Screen + Friends: + {route.params.friends[0]} + {route.params.friends[1]} + {route.params.friends[2]} + + + ); } +// codeblock-focus-end + +const Stack = createNativeStackNavigator({ + initialRouteName: 'Home', + screens: { + Home: HomeScreen, + Profile: { + screen: ProfileScreen, + options: ({ route }) => ({ title: route.params.title }), + }, + }, +}); + +const Navigation = createStaticNavigation(Stack); + +function App() { + return ; +} + +export default App; ``` + + + +```js name="Navigate - setParams" snack version=7 dependencies=@react-navigation/elements +import * as React from 'react'; +import { Button } from '@react-navigation/elements'; +import { View, Text } from 'react-native'; +import { NavigationContainer } from '@react-navigation/native'; +import { createNativeStackNavigator } from '@react-navigation/native-stack'; + +function HomeScreen({ navigation: { navigate } }) { + return ( + + This is the home screen of the app + + + ); +} + +// codeblock-focus-start +function ProfileScreen({ navigation, route }) { + return ( + + Profile Screen + Friends: + {route.params.friends[0]} + {route.params.friends[1]} + {route.params.friends[2]} + + + + ); +} +// codeblock-focus-end + +const Stack = createNativeStackNavigator(); + +function App() { + return ( + + + + ({ title: route.params.title })} + /> + + + ); +} + +export default App; +``` + + + + ### `setOptions` The `setOptions` method lets us set screen options from within the component. This is useful if we need to use the component's props, state or context to configure our screen. - + + -```js +```js name="Navigate - setOptions" snack version=7 dependencies=@react-navigation/elements +import * as React from 'react'; +import { View, Text, TextInput } from 'react-native'; +import { Button } from '@react-navigation/elements'; +import { + useNavigation, + createStaticNavigation, +} from '@react-navigation/native'; +import { createNativeStackNavigator } from '@react-navigation/native-stack'; + +function HomeScreen() { + const navigation = useNavigation(); + + return ( + + This is the home screen of the app + + + ); +} + +// codeblock-focus-start +function ProfileScreen({ route }) { + const navigation = useNavigation(); + const [value, onChangeText] = React.useState(route.params.title); + + React.useEffect(() => { + // highlight-start + navigation.setOptions({ + title: value === '' ? 'No title' : value, + }); + // highlight-end + }, [navigation, value]); + + return ( + + + + + ); +} +// codeblock-focus-end + +const Stack = createNativeStackNavigator({ + initialRouteName: 'Home', + screens: { + Home: HomeScreen, + Profile: { + screen: ProfileScreen, + options: ({ route }) => ({ title: route.params.title }), + }, + }, +}); + +const Navigation = createStaticNavigation(Stack); + +function App() { + return ; +} + +export default App; +``` + + + + +```js name="Navigate - setOptions" snack version=7 dependencies=@react-navigation/elements +import * as React from 'react'; +import { View, Text, TextInput } from 'react-native'; +import { Button } from '@react-navigation/elements'; +import { NavigationContainer } from '@react-navigation/native'; +import { createNativeStackNavigator } from '@react-navigation/native-stack'; + +function HomeScreen({ navigation: { navigate } }) { + return ( + + This is the home screen of the app + + + ); +} + +// codeblock-focus-start function ProfileScreen({ navigation, route }) { const [value, onChangeText] = React.useState(route.params.title); React.useEffect(() => { + // highlight-start navigation.setOptions({ title: value === '' ? 'No title' : value, }); + // highlight-end }, [navigation, value]); return ( @@ -193,12 +909,35 @@ function ProfileScreen({ navigation, route }) { onChangeText={onChangeText} value={value} /> - ); } +// codeblock-focus-end + +const Stack = createNativeStackNavigator(); + +function App() { + return ( + + + + ({ title: route.params.title })} + /> + + + ); +} + +export default App; ``` + + + Any options specified here are shallow merged with the options specified when defining the screen. When using `navigation.setOptions`, we recommend specifying a placeholder in the screen's `options` prop and update it using `navigation.setOptions`. This makes sure that the delay for updating the options isn't noticeable to the user. It also makes it work with lazy-loaded screens. @@ -215,22 +954,132 @@ You can also use `React.useLayoutEffect` to reduce the delay in updating the opt Screens can add listeners on the `navigation` object with the `addListener` method. For example, to listen to the `focus` event: - + + -```js -function Profile({ navigation }) { - React.useEffect(() => { - const unsubscribe = navigation.addListener('focus', () => { - // do something - }); +```js name="Navigation events" snack version=7 dependencies=@react-navigation/elements +import * as React from 'react'; +import { View, Text } from 'react-native'; +import { Button } from '@react-navigation/elements'; +import { + useNavigation, + createStaticNavigation, +} 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( + () => navigation.addListener('focus', () => alert('Screen was focused')), + [navigation] + ); + + React.useEffect( + () => navigation.addListener('blur', () => alert('Screen was unfocused')), + [navigation] + ); - return unsubscribe; - }, [navigation]); + return ( + + Profile Screen + + + ); +} +// codeblock-focus-end + +const SettingsStack = createNativeStackNavigator({ + screens: { + Settings: SettingsScreen, + Profile: ProfileScreen, + }, +}); + +const Navigation = createStaticNavigation(SettingsStack); + +export default function App() { + return ; +} +``` + + + + +```js name="Navigation events" snack version=7 dependencies=@react-navigation/elements +import * as React from 'react'; +import { View, Text } from 'react-native'; +import { Button } from '@react-navigation/elements'; +import { NavigationContainer } 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( + () => navigation.addListener('focus', () => alert('Screen was focused')), + [navigation] + ); + + React.useEffect( + () => navigation.addListener('blur', () => alert('Screen was unfocused')), + [navigation] + ); + + return ( + + Profile Screen + + + ); +} +// codeblock-focus-end + +const SettingsStack = createNativeStackNavigator(); - return ; +export default function App() { + return ( + + + + + + + ); } ``` + + + See [Navigation events](navigation-events.md) for more details on the available events and the API usage. ### `isFocused` @@ -348,12 +1197,28 @@ It accepts an optional ID parameter to refer to a specific parent navigator. For To use an ID for a navigator, first pass a unique `id` prop: + + + +```js +const Drawer = createDrawerNavigator({ + id: 'LeftDrawer', + screens: { + /* content */ + }, +}); +``` + + + + ```js - - {/* .. */} - +{/* .. */} ``` + + + Then when using `getParent`, instead of: ```js