React Navigation. Reactnavigation

1. Preparation

1.1 Minimum Requirements

React Navigation 6 requires the React – Native version to be at least 0.63.0.

1.2 Installation Dependencies

Install the required packages in the React Native project:

yarn add @react-navigation/native@next
Copy the code

React-native Stage-handler, react-native reanimated, react-native screens, and react-native Safe-area-Context need to be installed.

yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context
Copy the code

1.2.1

If you are developing iOS projects on a MAC, you will need to install CocoaPods to complete the project link:

npx pod-install ios
Copy the code

1.2.2 the react – native – screens

The react – native – screens in Android need to modify the Android/app/SRC/main/Java / < your package name > / MainActivity. Java file.

Add the following code to the MainActivity class:

import android.os.Bundle;

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(null);
}

Copy the code

1.2.3 the react – native – gesture – handler

The react – native – gesture – handler in Android also need to modify the Android/app/SRC/main/Java / < your package name > / MainActivity. Java file.

package com.swmansion.gesturehandler.react.example;

import com.facebook.react.ReactActivity;
+ import com.facebook.react.ReactActivityDelegate;
+ import com.facebook.react.ReactRootView;
+ import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;

public class MainActivity extends ReactActivity {

  @Override
  protected String getMainComponentName() {
    return "Example";
  }

+  @Override
+  protected ReactActivityDelegate createReactActivityDelegate(){+return new ReactActivityDelegate(this, getMainComponentName()) {
+      @Override
+      protected ReactRootView createRootView(){+return newRNGestureHandlerEnabledRootView(MainActivity.this); + +}}; +}}Copy the code

Details: docs.swmansion.com/react-nativ…

After installing the react-native Gesture-handler, introduce the react-native Gesture-handler in the project’s entry file (e.g. index.js or app.js) (make sure it’s on the first line of the entry file)

Note: If you ignore this step, it will crash in production, although it will work fine in development.

import 'react-native-gesture-handler';
import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';

export default function App() {
  return (
    <NavigationContainer>{/* Rest of your app code */}</NavigationContainer>
  );
}
Copy the code

1.3 Hello React Navigation

Install the stack navigation library

yarn add @react-navigation/native-stack@next
Copy the code

Notice that @react-Navigation /native stack depends on the React-native Screens library

The createStackNavigator function returns an object containing two properties: the screen and the navigator. These are the React components used to configure the navigator. The navigator should define the configuration of the route with screen elements as child elements.

NavigationContainer is a component that manages the navigation tree and contains navigation state. This component must wrap all navigator structures. Typically, we render this component in the root directory of the application, which is usually the exported component from app.js. Here I made a custom route file and introduced it in app.js:

import 'react-native-gesture-handler';
import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

function HomeScreen() {
  return (
    <View style={{ flex: 1.alignItems: 'center', justifyContent: 'center' }}>
      <Text>Home Screen</Text>
    </View>
  );
}

const Stack = createNativeStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

export default App;
Copy the code

The name of the route is case-insensitive — you can use lowercase HOME or uppercase HOME. However, common route names are in uppercase.

1.3.1 specify the options

<Stack.Screen
  name="Home"
  component={HomeScreen}
  options={{ title: 'Overview'}} / >Copy the code

1.3.2 transfer props

<Stack.Screen name="Home">
    {props= > <HomeScreen {. props} extraData={someData} />}
</Stack.Screen>
Copy the code

React Navigation Usage guide

Tab navigation

Install dependencies:

yarn add @react-navigation/bottom-tabs@next
Copy the code

The sample

import * as React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import IconFont from '.. /src/iconfont';


function HomeScreen() {
  return (
    <View style={{ flex: 1.justifyContent: 'center', alignItems: 'center' }}>
      <Text>Home!</Text>
    </View>
  );
}

function SettingsScreen() {
  return (
    <View style={{ flex: 1.justifyContent: 'center', alignItems: 'center' }}>
      <Text>Settings!</Text>
    </View>
  );
}

const Tab = createBottomTabNavigator();

function MyTabs() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Home" component={HomeScreen} />
      <Tab.Screen name="Settings" component={SettingsScreen} />
    </Tab.Navigator>
  );
}

export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator
        screenOptions={({ route}) = > ({
          tabBarIcon: ({ focused, color, size }) => {
            console.log('color: ', color);
            if (route.name === 'Home') {
              return <IconFont name="iconshouye" size={size} color={color} />;
            } else if (route.name === 'Settings') {
              return <IconFont name="iconshezhi1" size={size} color={color} />;
            }
          },
          tabBarActiveTintColor: 'tomato',
          tabBarInactiveTintColor: 'gray',
        })}>
        <Tab.Screen name="Home" component={HomeScreen} options={{ tabBarBadge: 3}} / >
        <Tab.Screen name="Settings" component={SettingsScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}

Copy the code

  1. TabBarActiveTintColor Indicates the TabBarIcon selected color, and tabBarInactiveTintColor indicates the unselected color.

  2. tabBarBadge

<Tab.Screen
  name="Home"
  component={HomeScreen}
  options={{ tabBarBadge: 3}} / >Copy the code

Drawer navigation

Install dependencies:

yarn add @react-navigation/drawer@next
Copy the code

The sample

import 'react-native-gesture-handler';
import * as React from 'react';
import { View, Button, Text, Image, Alert } from 'react-native';
import { NavigationContainer, DrawerActions } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import {
  createDrawerNavigator,
  DrawerContentScrollView,
  DrawerItemList,
  DrawerItem,
} from '@react-navigation/drawer';

function Feed({ navigation }) {
  return (
    <View style={{ flex: 1.justifyContent: 'center', alignItems: 'center' }}>
      <Text>Feed Screen</Text>
      <Button title="Open drawer" onPress={()= > navigation.openDrawer()} />
      <Button
        title="Toggle drawer"
        onPress={()= > navigation.dispatch(DrawerActions.toggleDrawer())}
      />
    </View>
  );
}

function Notifications() {
  return (
    <View style={{ flex: 1.justifyContent: 'center', alignItems: 'center' }}>
      <Text>Notifications Screen</Text>
    </View>
  );
}

function CustomDrawerContent(props) {
  return (
    <DrawerContentScrollView {. props} >
      <DrawerItemList {. props} / >
      <DrawerItem
        label="Close drawer"
        onPress={()= > props.navigation.closeDrawer()}
      />
      <DrawerItem
        label="Toggle drawer"
        onPress={()= > props.navigation.toggleDrawer()}
      />
    </DrawerContentScrollView>
  );
}

const Drawer = createDrawerNavigator();

function MyDrawer() {
  return (
    <Drawer.Navigator
      drawerContent={props= > <CustomDrawerContent {. props} / >} ><Drawer.Screen name="Feed" component={Feed} />
      <Drawer.Screen name="Notifications" component={Notifications} />
    </Drawer.Navigator>
  );
}

export default function App() {
  return (
    <NavigationContainer>
      <MyDrawer />
    </NavigationContainer>
  );
}
Copy the code

Mode of switchover of drawers:

  1. Navigation. OpenDrawer (), navigation. CloseDrawer ();

  2. navigation.toggleDrawer();

  3. Navigation. Dispatch (DrawerActions openDrawer ()), navigation, dispatch (DrawerActions. CloseDrawer ()), navigation, dispatch (on Dra werActions.toggleDrawer());

Liu Haibing

React Native uses the react-native safe-area-context library to handle bangs.

  • Render without header navigation or tabBar navigation
import * as React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

function Demo() {
  return (
    <View
      style={{
        flex: 1.justifyContent: 'space-between',
        alignItems: 'center'}} >
      <Text>This is top text.</Text>
      <Text>This is bottom text.</Text>
    </View>
  );
}
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator
        initialRouteName="Home"
        screenOptions={{ headerShown: false}} >
        <Stack.Screen name="Home">{() = > (<Tab.Navigator
              initialRouteName="Analitics"
              tabBar={()= > null}
              screenOptions={{ headerShown: false }}>
              <Tab.Screen name="Analitics" component={Demo} />
              <Tab.Screen name="Profile" component={Demo} />
            </Tab.Navigator>
          )}
        </Stack.Screen>

        <Stack.Screen name="Settings" component={Demo} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

Copy the code

  • usereact-native-safe-area-context
import * as React from 'react';
import { Text } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';

function Demo() {
  return (
    <SafeAreaView
      style={{
        flex: 1.justifyContent: 'space-between',
        alignItems: 'center'}} >
      <Text>This is top text.</Text>
      <Text>This is bottom text.</Text>
    </SafeAreaView>
  );
}

const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();

export default function App() {
  return (
    <SafeAreaProvider>
      <NavigationContainer>
        <Stack.Navigator
          initialRouteName="Home"
          screenOptions={{ headerShown: false}} >
          <Stack.Screen name="Home">{() = > (<Tab.Navigator
                initialRouteName="Analitics"
                tabBar={()= > null}
                screenOptions={{ headerShown: false }}>
                <Tab.Screen name="Analitics" component={Demo} />
                <Tab.Screen name="Profile" component={Demo} />
              </Tab.Navigator>
            )}
          </Stack.Screen>
          <Stack.Screen name="Settings" component={Demo} />
        </Stack.Navigator>
      </NavigationContainer>
    </SafeAreaProvider>
  );
}

Copy the code

Using Hook mode

import * as React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createStackNavigator } from '@react-navigation/stack';
import {
  SafeAreaProvider,
  useSafeAreaInsets,
} from 'react-native-safe-area-context';

function Demo() {
  const insets = useSafeAreaInsets();
  return (
    <View
      style={{
        paddingTop: insets.top, / /paddingBottom: insets.bottom.flex: 1.justifyContent: 'space-between',
        alignItems: 'center'}} >
      <Text>This is top text.</Text>
      <Text>This is bottom text.</Text>
    </View>
  );
}

const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();

export default function App() {
  return (
    <SafeAreaProvider>
      <NavigationContainer>
        <Stack.Navigator
          initialRouteName="Home"
          screenOptions={{ headerShown: false}} >
          <Stack.Screen name="Home">{() = > (<Tab.Navigator
                initialRouteName="Analitics"
                tabBar={()= > null}
                screenOptions={{ headerShown: false }}>
                <Tab.Screen name="Analitics" component={Demo} />
                <Tab.Screen name="Profile" component={Demo} />
              </Tab.Navigator>
            )}
          </Stack.Screen>

          <Stack.Screen name="Settings" component={Demo} />
        </Stack.Navigator>
      </NavigationContainer>
    </SafeAreaProvider>
  );
}

Copy the code

Key codes:

  • const insets = useSafeAreaInsets()
  • style={{paddingTop: insets.top,... }}

Different status bar configurations based on routes

If you don’t have a navigation title, or if your navigation title changes color based on the route, you need to make sure you use the correct color for your content.

Stack navigation

import * as React from 'react';
import { Text, StatusBar, Button, StyleSheet } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';

function Screen1({ navigation }) {
  return (
    <SafeAreaView style={[styles.container, { backgroundColor: '#6a51ae' }]}>
      <StatusBar barStyle="light-content" backgroundColor="#6a51ae" />
      <Text style={{ color: '#fff' }}>Light Screen</Text>
      <Button
        title="Next screen"
        onPress={()= > navigation.navigate('Screen2')}
      />
    </SafeAreaView>
  );
}

function Screen2({ navigation }) {
  return (
    <SafeAreaView style={[styles.container, { backgroundColor: '#ecf0f1' }]}>
      <StatusBar barStyle="dark-content" backgroundColor="#ecf0f1" />
      <Text>Dark Screen</Text>
      <Button
        title="Next screen"
        onPress={()= > navigation.navigate('Screen1')}
      />
    </SafeAreaView>
  );
}

const Stack = createNativeStackNavigator();

export default function App() {
  return (
    <SafeAreaProvider>
      <NavigationContainer>
        <Stack.Navigator screenOptions={{ headerShown: false}} >
          <Stack.Screen name="Screen1" component={Screen1} />
          <Stack.Screen name="Screen2" component={Screen2} />
        </Stack.Navigator>
      </NavigationContainer>
    </SafeAreaProvider>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1.justifyContent: 'center'.alignItems: 'center'}});Copy the code

Label navigation and drawer navigation

If you use a TAB or drawer navigator, it’s a little more complicated and the StatusBar configuration may be overwritten.

To solve this problem, we must let the status bar component know the screen focus and render it only when the screen is in focus. We can do this by using the useIsFocused hook and creating a wrapper component.

import * as React from 'react';
import { StatusBar } from 'react-native';
import { useIsFocused } from '@react-navigation/native';

function FocusAwareStatusBar(props) {
  const isFocused = useIsFocused();

  return isFocused ? <StatusBar {. props} / > : null;
}
Copy the code

At this point screen1.js and screen2.js will use the FocusAwareStatusBar component instead of the React Native StatusBar component.

function Screen1({ navigation }) {
  return (
    <SafeAreaView style={[styles.container, { backgroundColor: '#6a51ae' }]}>
      <FocusAwareStatusBar barStyle="light-content" backgroundColor="#6a51ae" />
      <Text style={{ color: '#fff' }}>Light Screen</Text>
      <Button
        title="Next screen"
        onPress={()= > navigation.navigate('Screen2')}
        color="#fff"
      />
    </SafeAreaView>
  );
}

function Screen2({ navigation }) {
  return (
    <SafeAreaView style={[styles.container, { backgroundColor: '#ecf0f1' }]}>
      <FocusAwareStatusBar barStyle="dark-content" backgroundColor="#ecf0f1" />
      <Text>Dark Screen</Text>
      <Button
        title="Next screen"
        onPress={()= > navigation.navigate('Screen1')}
      />
    </SafeAreaView>
  );
}
Copy the code

Monitor screen focus

navigation.addListener

import * as React from 'react';
import { View } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

function ProfileScreen({ navigation }) {
  React.useEffect(() = > {
    const unsubscribe = navigation.addListener('focus'.() = > {
      alert('Screen is focused');
    });
    // Return the function to unsubscribe from the event so it gets removed on unmount
    returnunsubscribe; } []);return <View />;
}

function HomeScreen() {
  return <View />;
}

const Tab = createBottomTabNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen name="Home" component={HomeScreen} />
        <Tab.Screen name="Profile" component={ProfileScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}

Copy the code

useFocusEffect

import * as React from 'react';
import { View } from 'react-native';
import { NavigationContainer, useFocusEffect } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

function ProfileScreen() {
  useFocusEffect(
    React.useCallback(() = > {
      alert('Screen was focused');
      // Do something when the screen is focused
      return () = > {
        alert('Screen was unfocused');
        // Do something when the screen is unfocused
        // Useful for cleanup functions}; }, []));return <View />;
}

function HomeScreen() {
  return <View />;
}

const Tab = createBottomTabNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen name="Home" component={HomeScreen} />
        <Tab.Screen name="Profile" component={ProfileScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}

Copy the code

useIsFocused

import * as React from 'react';
import { View, Text } from 'react-native';
import { NavigationContainer, useIsFocused } from '@react-navigation/native';
import { createMaterialTopTabNavigator } from '@react-navigation/material-top-tabs';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';

function ProfileScreen() {
  // This hook returns `true` if the screen is focused, `false` otherwise
  const isFocused = useIsFocused();

  return (
    <View style={{ flex: 1.alignItems: 'center', justifyContent: 'center' }}>
      <Text>{isFocused ? 'focused' : 'unfocused'}</Text>
    </View>
  );
}

function HomeScreen() {
  return <View />;
}

const Tab = createMaterialTopTabNavigator();

export default function App() {
  return (
    <SafeAreaProvider>
      <NavigationContainer>
        <Tab.Navigator tabBarPosition="top" style={{ marginTop: 24}} >
          <Tab.Screen name="Home" component={HomeScreen} />
          <Tab.Screen name="Profile" component={ProfileScreen} />
        </Tab.Navigator>
      </NavigationContainer>
    </SafeAreaProvider>
  );
}

Copy the code

Any component accesses the navigation

useNavigation

import * as React from 'react';
import { Button } from 'react-native';
import { useNavigation } from '@react-navigation/native';

function GoToButton({ screenName }) {
  const navigation = useNavigation();

  return (
    <Button
      title={`Go toThe ${screenName} `}onPress={()= > navigation.navigate(screenName)}
    />
  );
}
Copy the code

Navigate the jump without navigation prop

Sometimes navigation operations need to be triggered from places where navigation prop is not accessible, such as Redux middleware. In this case, navigation operations can be scheduled from the navigation container.

UseNavigation is used if navigation from within a component does not require passing down the navigation method. If the navigation needs to be passed down, the RootNavigation object can be accessed via ref and passed to the RootNavigation that we will use for navigation later.

// App.js

import { NavigationContainer } from '@react-navigation/native';
import { navigationRef } from './RootNavigation';

export default function App() {
  return (
    <NavigationContainer ref={navigationRef}>{/ *... * /}</NavigationContainer>
  );
}
Copy the code
// RootNavigation.js

import { createNavigationContainerRef } from '@react-navigation/native';

export const navigationRef = createNavigationContainerRef()

export function navigate(name, params) {
  if(navigationRef.isReady()) { navigationRef.navigate(name, params); }}Copy the code

Additional navigation actions can also be added:

import { StackActions } from '@react-navigation/native';

// ...

export function push(. args) {
  if (navigationRef.isReady()) {
    navigationRef.dispatch(StackActions.push(...args));
  }
}
Copy the code

Let me give you an example

import * as React from 'react';
import { View, Button, Text } from 'react-native';
import {
  NavigationContainer,
  createNavigationContainerRef,
} from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

const navigationRef = createNavigationContainerRef();

function navigate(name, params) {
  if(navigationRef.isReady()) { navigationRef.navigate(name, params); }}function Home() {
  return (
    <View style={{ flex: 1.alignItems: 'center', justifyContent: 'center' }}>
      <Button
        title="Go to Settings"
        onPress={()= > navigate('Settings', { userName: 'Lucy' })}
      />
    </View>
  );
}

function Settings({ route }) {
  return (
    <View style={{ flex: 1.alignItems: 'center', justifyContent: 'center' }}>
      <Text>Hello {route.params.userName}</Text>
      <Button title="Go to Home" onPress={()= > navigate('Home')} />
    </View>
  );
}

const RootStack = createNativeStackNavigator();

export default function App() {
  return (
    <NavigationContainer ref={navigationRef}>
      <RootStack.Navigator>
        <RootStack.Screen name="Home" component={Home} />
        <RootStack.Screen name="Settings" component={Settings} />
      </RootStack.Navigator>
    </NavigationContainer>
  );
}

Copy the code

React Navigation TypeScript

navigator

To type check our route names and parameters, the first thing we need to do is create an object type that contains the mapping of route names to route parameters. For example, suppose we have a route named Profile in the root navigator, which should have one parameter, userId:

type RootStackParamList = {
  Profile: { userId: string };
};
Copy the code

Again, we need to do the same thing for each route:

type RootStackParamList = {
  Home: undefined;
  Profile: { userId: string };
  Feed: { sort: 'latest' | 'top' } | undefined;
};
Copy the code

Specifying undefined means that the route has no parameters.

After defining the mapping, we need to tell the navigator to use it. To do this, we can pass it as a generic to the createXNavigator function:

import { createStackNavigator } from '@react-navigation/stack';

const RootStack = createStackNavigator<RootStackParamList>();
Copy the code

use

<RootStack.Navigator initialRouteName="Home">
  <RootStack.Screen name="Home" component={Home} />
  <RootStack.Screen
    name="Profile"
    component={Profile}
    initialParams={{ userId: user.id}} / >
  <RootStack.Screen name="Feed" component={Feed} />
</RootStack.Navigator>
Copy the code

screens

import { NativeStackScreenProps } from '@react-navigation/native-stack';

type RootStackParamList = {
  Home: undefined;
  Profile: { userId: string };
  Feed: { sort: 'latest' | 'top' } | undefined;
};

type Props = NativeStackScreenProps<RootStackParamList, 'Profile'>;
Copy the code

NativeStackScreenProps requires two generics, the param list object we defined earlier, and the name of the current route.

In the same way, You can import StackScreenProps for @react-navigation/stack, DrawerScreenProps from @react-navigation/drawer, BottomTabScreenProps From @react-navigation/bottom-tabs etc.

For the function components:

function ProfileScreen({ route, navigation }: Props) {
  // ...
}
Copy the code

For class components:

class ProfileScreen extends React.Component<Props> {
  render() {
    // ...}}Copy the code

We can get the types of navigation and route from the Props type:

type ProfileScreenNavigationProp = Props['navigation'];

type ProfileScreenRouteProp = Props['route'];
Copy the code

Alternatively, you can define props for navigation and route respectively.

  • fornavigation propsSay, to getnavigationWe need to import the corresponding type from the navigator.
import { NativeStackNavigationProp } from '@react-navigation/native-stack';

type ProfileScreenNavigationProp = NativeStackNavigationProp<
  RootStackParamList,
  'Profile'
>;
Copy the code

In the same way, You can also import import {StackNavigationProp} from ‘@react-navigation/stack’, import {DrawerNavigationProp} from ‘@react-navigation/drawer’, import {BottomTabNavigationProp} from ‘@react-navigation/bottom-tabs’

  • forrouteProp, we need to use it@react-navigation/nativeIn theRoutePropType.
import { RouteProp } from '@react-navigation/native';

type ProfileScreenRouteProp = RouteProp<RootStackParamList, 'Profile'>;
Copy the code

Nested navigation

Check out Screens and Params in the nested navigator
function Home() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Feed" component={Feed} />
      <Tab.Screen name="Messages" component={Messages} />
    </Tab.Navigator>
  );
}

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen
          name="Home"
          component={Home}
          options={{ headerShown: false}} / >
        <Stack.Screen name="Profile" component={Profile} />
        <Stack.Screen name="Settings" component={Settings} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}
Copy the code

In the nested navigation above, you can navigate to the screen in the nested navigation by passing the Screen and Params properties of the nested screen.

navigation.navigate('Home', {
  screen: 'Feed'.params: { sort: 'latest'}});Copy the code

In order to be able to do type checking, we need to extract the parameters from the screen that contains the nested navigation. This can be done using NavigatorScreenParams.

import { NavigatorScreenParams } from '@react-navigation/native';

type TabParamList = {
  Home: NavigatorScreenParams<StackParamList>;
  Profile: { userId: string };
};
Copy the code

Integrated navigation

When a navigator is nested, the navigation item on the screen is a combination of multiple navigation items. For example, if we have a TAB in the stack, the navigation property will have both jumpTo (from the TAB navigator) and push (from the stack navigator). To make it easier to combine types from multiple navigators, you can use the CompositeScreenProps type.

import { CompositeScreenProps } from '@react-navigation/native';
import { BottomTabScreenProps } from '@react-navigation/bottom-tabs';
import { StackScreenProps } from '@react-navigation/stack';

type ProfileScreenNavigationProp = CompositeScreenProps<
  BottomTabScreenProps<TabParamList, 'Profile'>,
  StackScreenProps<StackParamList>
>;
Copy the code

For multiple parent navigators, this helper type should be nested:

type ProfileScreenNavigationProp = CompositeScreenProps<
  BottomTabScreenProps<TabParamList, 'Profile'>,
  CompositeScreenProps<
    StackScreenProps<StackParamList>,
    DrawerScreenProps<DrawerParamList>
  >
>;
Copy the code

If navigation is annotated separately, a CompositeNavigationProp can be used instead. Usage is similar to CompositeScreenProps:

import { CompositeNavigationProp } from '@react-navigation/native';
import { BottomTabNavigationProp } from '@react-navigation/bottom-tabs';
import { StackNavigationProp } from '@react-navigation/stack';

type ProfileScreenNavigationProp = CompositeNavigationProp<
  BottomTabNavigationProp<TabParamList, 'Profile'>,
  StackNavigationProp<StackParamList>
>;
Copy the code

The statement useNavigation

const navigation = useNavigation<ProfileScreenNavigationProp>();
Copy the code

The statement useRoute

const route = useRoute<ProfileScreenRouteProp>();
Copy the code

Declare options, screenOptions

import { StackNavigationOptions } from '@react-navigation/stack';

const options: StackNavigationOptions = {
  headerShown: false};Copy the code

In the same way, You can also import import {DrawerNavigationOptions} from ‘@ the react – navigation/drawer, import the from {BottomTabNavigationOptions} ‘@ the react – navigation/bottom – tabs, and so on.

Declare ref, NavigationContainer

createNavigationContainerRef

If you use createNavigationContainerRef () method to create a ref, you can type checking through the following ways:

import { createNavigationContainerRef } from '@react-navigation/native';

// ...

const navigationRef = createNavigationContainerRef<RootStackParamList>();
Copy the code
useNavigationContainerRef
import { createNavigationContainerRef } from '@react-navigation/native';

// ...

const navigationRef = useNavigationContainerRef<RootStackParamList>();
Copy the code
useRef
import { NavigationContainerRef } from '@react-navigation/native';

// ...

const navigationRef = React.useRef<NavigationContainerRef<RootStackParamList>>(null);
Copy the code
createRef
import { NavigationContainerRef } from '@react-navigation/native';

// ...

const navigationRef = React.createRef<NavigationContainerRef<RootStackParamList>>();
Copy the code

React Navigation has several important apis

Group

The Group component is used to Group multiple screens within the navigator.

const Stack = createStackNavigator(); // Stack contains Screen & Navigator properties

<Stack.Navigator>
  <Stack.Group
    screenOptions={{ headerStyle: { backgroundColor: 'papayawhip'}}} >
    <Stack.Screen name="Home" component={HomeScreen} />
    <Stack.Screen name="Profile" component={ProfileScreen} />
  </Stack.Group>
  <Stack.Group screenOptions={{ presentation: 'modal' }}>
    <Stack.Screen name="Search" component={SearchScreen} />
    <Stack.Screen name="Share" component={ShareScreen} />
  </Stack.Group>
</Stack.Navigator>
Copy the code

Props

screenOptions
<Stack.Group
  screenOptions={{
    presentation: 'modal',}} > {/* screens */}
</Stack.Group>
Copy the code
<Stack.Group
  screenOptions={({ route, navigation }) = > ({
    title: route.params.title,
  })}
>
  {/* screens */}
</Stack.Group>
Copy the code

Screen

const Stack = createNativeStackNavigator(); // Stack contains Screen & Navigator properties

<Stack.Navigator>
  <Stack.Screen name="Home" component={HomeScreen} />
  <Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>

Copy the code

Props

name
<Stack.Screen name="Profile" component={ProfileScreen} />
Copy the code

Name is used to jump to Screen:

navigation.navigate('Profile');
Copy the code
options

Options Options used to configure how the screen appears in the navigator. It accepts an object or a function that returns an object.

  • Accept an object
<Stack.Screen
  name="Profile"
  component={ProfileScreen}
  options={{
    title: 'Awesome app',
  }}
/>
Copy the code
  • Accepts a function that returns an object
<Stack.Screen
  name="Profile"
  component={ProfileScreen}
  options={({ route, navigation }) = > ({
    title: route.params.userId,
  })}
/>
Copy the code
  • initialParams
<Stack.Screen
  name="Details"
  component={DetailsScreen}
  initialParams={{ itemId: 42}} / >Copy the code
  • getId
<Stack.Screen
  name="Profile"
  component={ProfileScreen}
  getId={({ params }) = > params.userId}
/>
Copy the code
  • component
<Stack.Screen name="Profile" component={ProfileScreen} />
Copy the code
  • getComponent
<Stack.Screen
  name="Profile"
  getComponent={() = > require('./ProfileScreen').default}
/>
Copy the code
  • children
<Stack.Screen name="Profile">
  {(props) = > <ProfileScreen {. props} / >}
</Stack.Screen>
Copy the code

Route prop

key

A unique key for the screen that is automatically created or added when navigating to this screen.

name

Screen name.

path

An optional string of paths to open screens when opened via deep link.

params

An optional object containing the parameters defined during navigation, such as navigate(‘Twitter’, {user: ‘Dan Abramov’}).

function ProfileScreen({ route }) {
  return (
    <View>
      <Text>This is the profile screen of the app</Text>
      <Text>{route.name}</Text>
    </View>
  );
}
Copy the code

The resources

react-navigation