React Navigation

In a multi-page application, the jump to a page is done through a route or navigator. In the early days of RN application development, the Navigator component could be used directly. However, starting with version 0.44, Navigator was officially removed from the React Native core component library. In the React-Native – Deprecated – custom-Components module, and the Navigator component is no longer officially recommended. In this case, we can choose React Navigation, which is open-source by the React Native community.

As with previous versions, React Navigation supports three Navigation types: StackNavigator, TabNavigator, and DrawerNavigator.

  • StackNavigator: A page navigation component that contains navigation bars, similar to the official Navigator component.
  • TabNavigator: Displays the tabBar’s page navigation component at the bottom.
  • DrawerNavigator: Navigation component used to implement sidebar drawer pages.

1.1 installation

Before using React Navigation, install the required software packages in your React Native project, including NPM and YARN, as shown below.

npm install @react-navigation/native
/ / or
yarn add @react-navigation/native  
Copy the code

So far, the packages we have installed are required by some of the infrastructure of navigation, and to create different navigation stack effects, you need to install a separate plugin. Common plug-ins are as follows: react-native-gesture-handler, react-native-reanimated, React-native screens, react-native safe-area-context and @react-native community/ marshall-view, then run the following command to install the plugin.

npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
Copy the code

The required dependency libraries are as follows:

  • React-native gesture-handler: used to switch pages with gestures.
  • React-native – Screens: For the native layer to free up unshown pages and improve app memory usage.
  • React-native safe-area-context: ensures that the page is displayed in a secure area (mainly for bangs).
  • React-native community/ marshall-view: Use the color Settings to return buttons in the header navigation bar.
  • React navigation/native is the core of react navigation.

React-native – Reanimated is only available when using DrawerNavigator. If you want to install react-native- Reanimated, you can install either of them.

React Native 0.60 and later versions do not need to run the React-Native link to install the Native library. If the Native library is not connected, you can also use the following command to install the Native library.

npx pod-install ios
Copy the code

1.2 RN’s prompt plug-in

I haven’t paid much attention to RN since React Native Mobile Development 2nd Edition was published in 2019. And because of the WebStrom update, it seems that the plugins installed before are invalid.

In RN development, writing code is a pain without installing the code prompt plug-in, but I was able to do so with my old reactnative.xml. The steps to install reactnative.xml are as follows: ReactNative. XML 2. Then/Users/MAC/Library/Application Support/JetBrains WebStorm2020.1 new templates/directory file, and the above download ReactNative. XML copy in. 3, restart WebStrom and you will see the prompt

Hello React Navigation

In Web browser application development, we can use anchors (tags) to link to different pages, and when the user clicks on the link, the URL is pushed onto the browser history stack. When the user presses the back button, the browser pops up previously visited pages from the top of the history stack. In React Native development, we can use the Stack navigator of React Navigation to manage page jumps and Navigation stack management.

In order to manage the stack of multiple pages, we need to use the createStackNavigator component provided by React Navigation and make sure that the following plugin is installed before using it.

npm install @react-navigation/stack
Copy the code

2.1 Stack navigator

CreateStackNavigator is a function that returns an object containing two properties, the screen and the navigator, which are used to configure the React component of the navigator. NavigationContainer, on the other hand, is a component that manages the navigation tree and contains navigation state, which must wrap all navigator structures.

To do this, we create a new app.js file that manages the routing page and add the following code:

// In App.js in a new project

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

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

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

export default App;
Copy the code

Then, we change the path of the entry file of the RN project’s index.js file to the path of the app.js file above, and run the project with the effect shown below.

2.2 Configuring the Navigator

All the routing configurations will correspond to the properties on the navigator, since we haven’t set any of our navigator’s properties yet and are using the default configuration, now let’s add a second screen to our stack navigator.

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

const Stack = createStackNavigator(a);function App(a) {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}
Copy the code

Now we have two routes in the routing stack, one is Home and the other is Details. We can add routes by adding Screen components. The Screen component has a name property that specifies the name of the route and a Component property that specifies the component we will render. In the sample code above, the Home route corresponds to the HomeScreen component and the Details route corresponds to the DetailsScreen component.

It should be noted that the Component property receives the component and not a Render () method. So don’t pass it an inline function (such as Component ={()=>}) or your component will lose all state when unloaded and reloaded.

2.3 Setting the Option Parameter

Each routing page in the navigator can set some parameters, such as title.

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

If you want to pass some additional properties, you can also use a Render function as a component property, as shown below.

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

3. Routing stack page hopping

A complete application is usually composed of multiple routes that can jump from one another. In Web browser application development, we can use the following way to realize the page jump.

<a href="details.html">Go to Details</a>
Copy the code

Of course, the following can also be used.

<a
  onClick={() => {
    window.location.href = 'details.html';
  }}
>
  Go to Details
</a>
Copy the code

3.1 Jump to a new page

React Navigation: How to jump to a new page? In React Navigation stack, the Navigation property will be passed to each screen component, so we can perform the page jump in the following way.

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

function HomeScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Home Screen</Text>
      <Button
        title="Go to Details"
        onPress={() => navigation.navigate('Details')}
      />
    </View>
  );
}

// ... other code from the previous section
Copy the code

In the code above, we use the navigation and navigate() methods.

  • Navigation: In the stack navigator, the navigation property is passed to each screen component.
  • Navigate () : We call the navigate method to give the page a jump.

Run the above code and it will look like the image below.What if we call the navigation.navigate method to jump to a route that we have not defined in the stack navigator? Nothing will happen.

3.2 Jumping to the Same Route Multiple times

What happens if we jump to the same routing page multiple times, as shown below.

function DetailsScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Details Screen</Text>
      <Button
        title="Go to Details... again"
        onPress={() => navigation.navigate('Details')}
      />
    </View>
  );
}
Copy the code

Run the code above and when you click “Go to Details”, nothing will happen because we are already on the Details page.

Now let’s say we want to add another detail page. This is a common scenario where we want to display different data on the same Details page. To achieve this, we can replace the navigate() method with the push() method, which adds new routes directly to the stack regardless of the current navigation history.

<Button
  title="Go to Details... again"
  onPress={() => navigation.push('Details')} / >Copy the code

Run the above code and it will look like the following image.

3.3 Route Return

By default, the navigation header provided by the stack navigator contains a back button that can be clicked to return to the previous page. This back button is not displayed if there is only one page in the navigation stack, that is, there is no page to return to.

If we are using a custom navigation header, we can use the navigation.goback () method to return the route, as shown below.

function DetailsScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Details Screen</Text>
      <Button
        title="Go to Details... again"
        onPress={() => navigation.push('Details')}
      />
      <Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
      <Button title="Go back" onPress={() => navigation.goBack()} />
    </View>
  );
}
Copy the code

Another common requirement is to return to multiple pages. For example, if you have multiple pages on your stack, you want to remove the pages one by one and return to the first page. In the scenario above, we want to return to the Home page, so we can use navigate(‘Home’).

The other method is navigation.poptotop (), which will return to the first page on the stack (the initial page), as shown below.

function DetailsScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Details Screen</Text>
      <Button
        title="Go to Details... again"
        onPress={() => navigation.push('Details')}
      />
      <Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
      <Button title="Go back" onPress={() => navigation.goBack()} />
      <Button
        title="Go back to first screen in stack"
        onPress={() => navigation.popToTop()}
      />
    </View>
  );
}
Copy the code

4. Route parameter transmission

4.1 Basic Usage

In the process of page hopping, it is inevitable to transfer data. In React Navigation, there are two main ways to pass parameters between routes:

  • Encapsulate the parameter into an object, and then treat this object asnavigation.navigateMethod to implement the route jump parameter passing.
  • useroute.params()Method reads the argument passed to it.

Either way, we recommend serializing the data that needs to be passed, as shown below.

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

function HomeScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Home Screen</Text>
      <Button
        title="Go to Details"
        onPress={() => {
          /* 1. Navigate to the Details route with params */
          navigation.navigate('Details', {
            itemId: 86,
            otherParam: 'anything you want here'}); }} /> </View> ); }function DetailsScreen({ route, navigation }) {
  /* 2. Get the param */
  const { itemId } = route.params;
  const { otherParam } = route.params;
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Details Screen</Text>
      <Text>itemId: {JSON.stringify(itemId)}</Text>
      <Text>otherParam: {JSON.stringify(otherParam)}</Text>
      <Button
        title="Go to Details... again"
        onPress={() =>
          navigation.push('Details', {
            itemId: Math.floor(Math.random(*)100),
          })
        }
      />
      <Button title="Go to Home" onPress={() => navigation.navigate('Home')} />
      <Button title="Go back" onPress={() => navigation.goBack()} />
    </View>
  );
}

const Stack = createStackNavigator(a);export default function App(a) {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

Copy the code

4.2 Updating Parameters

These parameters can also be updated on the routing page, and the navigation.setparams () method is used to update these parameters. Of course, we can also set the default values of the parameters we pass, and when we jump to the page without specifying their values, they will use the default values. Default values for parameters can be specified in the initialParams property, as shown below.

<Stack.Screen
  name="Details"
  component={DetailsScreen}
  initialParams={{ itemId: 42}} / >Copy the code

4.3 Returning parameters to the previous route

We will pass the data as parameters to a new routed page, or we can pass the data back to a previously routed page. For example, if you have a routing page that has a button to create a post, this button opens a new page to create a post, and after the post is created, you want to send some of the post’s data back to the previous page.

For this requirement, we can use navigate. If the route already exists on the stack, they look like goBack, and then just pass the data bound to the NVIGate params back to the previous page, as shown below.

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

function HomeScreen({ navigation, route }) {
  React.useEffect(() = > {if(route.params? .post) {// Post updated, do something with `route.params.post`
      // For example, send the post to the server
    }
  }, [route.params?.post]);

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Button
        title="Create post"
        onPress={() => navigation.navigate('CreatePost')}
      />
      <Text style={{ margin: 10}}>Post: {route.params? .post}</Text> </View> ); }function CreatePostScreen({ navigation, route }) {
  const [postText, setPostText] = React.useState("); return ( <> s on your mind?" style={{ height: 200, padding: 10, backgroundColor: 'white' }} value={postText} onChangeText={setPostText} /> Done" onPress={() => { // Pass params back to home screen navigation.navigate('Home', { post: postText }); }} / > < / a >); } const Stack = createStackNavigator(); export default function App() { return ( 
       
      modal"> Home" component={HomeScreen} /> CreatePost" component={CreatePostScreen} />   ); }Copy the code

When you click the [Done] button, the route.params on the home page will be updated and the text refreshed.

4.4 Parameters passed to the nested navigator

If you are involved in a scenario with nested navigators, you need to pass parameters in a slightly different way. For example, if you have a Settings page nested in the Acount page, and you want to pass parameters to the Settings page in the navigator, you can use the following approach.

navigation.navigate('Account', {
  screen: 'Settings',
  params: { user: 'jane'}});Copy the code

5. Navigation bar configuration

5.1 Setting the navigation Bar Title

The Screen component of React Navigation has an Options property, which contains many configurable options such as setting the title of the Navigation bar, as shown below.

function StackScreen(a) {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{ title: 'My home' }}
      />
    </Stack.Navigator>
  );
}
Copy the code

5.2 Use parameters in headings

To use parameters in the title, we can define the options property as a method that returns a configuration object. We can define options as a method and call it with React Navigation and pass in two available parameters {Navigation,route}, as shown below.

function StackScreen(a) {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{ title: 'My home' }}
      />
      <Stack.Screen
        name="Profile"
        component={ProfileScreen}
        options={({ route }) => ({ title: route.params.name })}
      />
    </Stack.Navigator>
  );
}
Copy the code

The argument passed to the Options method is an object with two properties, Navigation and Route.

  • Navigation: Navigation property of the routing screen component
  • Route: Route property of the screen component

5.3 Updating options with setOptions

Sometimes we need to update the options configuration of a loaded screen component. For this, we can use navigation. SetOptions.

/* Inside of render() of React class */
<Button
  title="Update the title"
  onPress={() => navigation.setOptions({ title: 'Updated! '})} / >Copy the code

5.4 Setting the Navigation Style

React Navigation supports custom Navigation header styles. We can use the following three style properties: headerStyle, headerTintColor, and headerTitleStyle.

  • HeaderStyle: Used to set the view style that wraps the navigation header, such as setting the background color for the navigation bar.
  • HeaderTintColor: Both the back button and title use this property to set their color.
  • HeaderTitleStyle: You can use properties if you want to customize the font, font size, and other text styles.
function StackScreen(a) {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{
          title: 'My home',
          headerStyle: {
            backgroundColor: '#f4511e',
          },
          headerTintColor: '#fff',
          headerTitleStyle: {
            fontWeight: 'bold',
          },
        }}
      />
    </Stack.Navigator>
  );
}
Copy the code

Here’s a link to the demo:Try the “header styles” example on Snack When customizing navigation styles, there are a few things to note:

  • On IOS, status bar text and ICONS are black, so setting the background color to dark might not look good.
  • The above Settings only work on the Home page; when we jump to the Details page, the default color is still displayed.

5.5 Sharing options parameters with Other Screen Components

Sometimes we need multiple pages to have the same navigation header style. So, we can use the stack navigator’s screenOptions property.

function StackScreen(a) {
  return (
    <Stack.Navigator
      screenOptions={{
        headerStyle: {
          backgroundColor: '#f4511e',
        },
        headerTintColor: '#fff',
        headerTitleStyle: {
          fontWeight: 'bold',
        },
      }} >
      <Stack.Screen
        name="Home"
        component={HomeScreen}
        options={{ title: 'My home' }} />
    </Stack.Navigator>
  );
}
Copy the code

In the example above, any page that belongs to StackScreen will use the same style of navigation header.

5.6 Custom components to replace the title property

Sometimes we want to do more with the title, such as replacing the text of the title with a picture, or putting the title inside a button. In these scenarios, we can override the title with a custom component, as shown below.

function LogoTitle(a) {
  return (
    <Image
      style={{ width: 50, height: 50 }}
      source={require('@expo/snack-static/react-native-logo.png')}
    />
  );
}

function StackScreen(a) {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Home"component={HomeScreen} options={{ headerTitle: props => <LogoTitle {... props} /> }}/> </Stack.Navigator> ); }Copy the code

6. Navigation bar buttons

6.1 Adding a Navigation Button

In general, we can use buttons in the navigation header to implement routing operations. For example, we can click the button on the left of the navigation bar to return to the previous route, and click the button on the right of the navigation header to do other operations, as shown below.

function StackScreen(a) {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Home"component={HomeScreen} options={{ headerTitle: props => <LogoTitle {... props} />, headerRight: () => ( <Button onPress={() =>alert('This is a button! ')}
              title="Info"
              color="#fff"
            />
          ),
        }}
      />
    </Stack.Navigator>
  );
}
Copy the code

6.2 Navigation header interaction with screen components

We only need to use navigation. SetOptions to realize the interaction between the button and the screen component. We can use navigation.

function StackScreen(a) {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Home"component={HomeScreen} options={({ navigation, route }) => ({ headerTitle: props => <LogoTitle {... props} />, })} /> </Stack.Navigator> ); }function HomeScreen({ navigation }) {
  const [count, setCount] = React.useState(0);

  React.useLayoutEffect(() => {
    navigation.setOptions({
      headerRight: () => (
        <Button onPress={() => setCount(c => c + 1)} title="Update count"/ >)}); }, [navigation]);return <Text>Count: {count}</Text>;
}
Copy the code

6.3 Customizing the Return button

CreateStackNavigator provides the platform’s default Back button. On IOS, there is a TAB next to the button that displays the abbreviation of the title of the previous page, or the word Back.

Also, developers can change the behavior of tags by setting headerBackTitle and headerTruncatedBackTitle, as shown below.

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

// ...

<Screen
  name="Home"component={HomeScreen} options={{ headerLeft: (props) => ( <HeaderBackButton {... props} onPress={() => {// Do something}} />),}} />;Copy the code

7. Nesting of navigation bar

Navigation nesting is when a navigator’s navigation page contains another navigator, for example.

function Home(a) {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Feed" component={Feed} />
      <Tab.Screen name="Messages" component={Messages} />
    </Tab.Navigator>
  );
}

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

In the example above, the Home component contains a TAB navigator. At the same time, the Home component is also a navigation page in the stack navigator, creating a scene of navigation nesting.

The nesting of navigators is similar to the nesting of components that we normally use, in that we usually nest multiple navigators.

7.1 How Can I Implement Navigation Nesting

When implementing navigator nesting, note the following:

1. Each navigator manages its own navigation stack

For example, when you click the back button on a nested stack navigator, it returns to the previous page in the navigation history of the nested stack navigator, not to the parent navigator.

2. Some of the navigator’s specific methods are also available in child navigators

If a Stack navigator is nested in a Drawer, the Drewer’s openDrawer and closeDrawer methods are still available in the navigation property of the nested Stack navigator. However, these methods are not accessible if the Stack navigator is not nested in the Drawer navigator.

Similarly, if you have a Tab navigator nested in the Stack navigator, the navigation property on the Tab navigator page will get the new push and replace methods.

3. Nested navigators do not respond to events from parent navigators

If the Stack navigator is nested within the tTab navigator, the Stack navigator’s page will not respond to events triggered by the parent Tab navigator, such as the tabPress event we bound with navigation.addListener. In order to be able to respond to the parent navigator events, we can use the navigation. DangerouslyGetParent (). The addListener to listen on the parent navigator events.

4. The parent navigator is rendered before the child navigator

What do we make of the above statement? If you nested a Stack navigator in a Drawer, you would see the Drawer rendered first and then the head of the Stack navigator, but if you nested a Drawer navigator in a Stack navigator, the head of the Stack navigator would be rendered first and then the Drawer. Therefore, we can use this phenomenon to determine which navigator nesting we need to select.

7.2 Jump from nested routines

Let’s take a look at the following code.

function Root(a) {
  return (
    <Stack.Navigator>
      <Stack.Screen name="Profile" component={Profile} />
      <Stack.Screen name="Settings" component={Settings} />
    </Stack.Navigator>
  );
}

function App(a) {
  return (
    <NavigationContainer>
      <Drawer.Navigator>
        <Drawer.Screen name="Home" component={Home} />
        <Drawer.Screen name="Root" component={Root} />
      </Drawer.Navigator>
    </NavigationContainer>
  );
}
Copy the code

If we now want to jump from the Home page to the Root page, we can use the following method.

navigation.navigate('Root');
Copy the code

However, at some point you may want to display the page you specify. To do this, you can include the name of the page in the parameter, as shown below.

navigation.navigate('Root',{screen:'Settings'});
Copy the code

Of course, we can also pass some parameters when the page jumps, as shown below.

navigation.navigate('Root', {
  screen: 'Settings',
  params: { user: 'jane'}});Copy the code

7.3 Nesting Multiple Navigation Bars

When multiple navigation bars of the stack or drawer are nested, the title of the child navigation bar and the parent navigation bar are displayed. However, it is usually preferable to display the title in the child navigator and hide the title in the stack navigator. In this case, we can use the navigation bar headerShown: false.

function Home(a) {
  return (
    <NestedStack.Navigator>
      <NestedStack.Screen name="Profile" component={Profile} />
      <NestedStack.Screen name="Settings" component={Settings} />
    </NestedStack.Navigator>
  );
}

function App(a) {
  return (
    <NavigationContainer>
      <RootStack.Navigator mode="modal">
        <RootStack.Screen
          name="Home"
          component={Home}
          options={{ headerShown: false }}
        />
        <RootStack.Screen name="EditPost" component={EditPost} />
      </RootStack.Navigator>
    </NavigationContainer>
  );
}
Copy the code

Life cycle of navigator

In the previous section, we introduced the basic usage of React Navigation and related routing. However, we do not know how routing enables page hops and returns.

If you’re familiar with the front-end Web, you’ll notice that when the user jumps from route A to Route B, A is unloaded (the componentWillUnmount method is called) and when the user returns to Page A from another page, page A is reloaded. The React lifecycle method still works in React Navigation, but it is not used in the same way as on the Web, and mobile Navigation is more complex.

8.1 Example

Suppose you have A Stack navigator with pages A and B in it. Its componentDidMount will be called when it needs to jump to the A page. CompouentDidMount is also called when A jump to B, but A remains loaded on the stack, so A’s componentWillUnmount method is not called.

However, when we return from B to A, compouentWillUnmount for B will be called, but componentDidMount for A will not be called because it has not been unmounted and remains loaded during the whole process.

The same is true for other types of navigators. Suppose you have a Tab navigator with two tabs, each of which is a Stack navigator.

function App(a) {
  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen name="First">
          {() => (
            <SettingsStack.Navigator>
              <SettingsStack.Screen
                name="Settings"
                component={SettingsScreen}
              />
              <SettingsStack.Screen name="Profile" component={ProfileScreen} />
            </SettingsStack.Navigator>
          )}
        </Tab.Screen>
        <Tab.Screen name="Second">
          {() => (
            <HomeStack.Navigator>
              <HomeStack.Screen name="Home" component={HomeScreen} />
              <HomeStack.Screen name="Details" component={DetailsScreen} />
            </HomeStack.Navigator>
          )}
        </Tab.Screen>
      </Tab.Navigator>
    </NavigationContainer>
  );
}
Copy the code

Now we jump from HomeScreen to the DetailsScreen page, and then use the TAB bar to jump from SettingScreen to ProfileScreen. At the end of this sequence, all four pages have been loaded, and if you use the TAB bar to return to HomeScreen, you’ll find that the DetailsScreen page’s navigation state to HomeStack has been saved.

8.2 React Navigation Lifecycle

As we know, React Native pages have their own life cycle. React Navigation does this by sending events to the component of the page that subscribed to them and listening for the user to leave and return events using the focus() and blur() methods.

function Profile({ navigation }) {
  React.useEffect(() = > {const unsubscribe = navigation.addListener('focus', () = > {// Screen was focused
      // Do something
    });
 
    return unsubscribe;
  }, [navigation]);
 
  return <ProfileContent />;
}
Copy the code

In fact, there is no need to manually add listeners. You can use the useFocusEffect hook to implement lifecycle listening, just like the React useEffect hook, except that useFocusEffect can only listen for the lifecycle of the user navigator, as shown below.

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

function Profile(a) {
  useFocusEffect(
    React.useCallback(() = > {// Do something when the screen is focused

      return() = > {// Do something when the screen is unfocused
        // Useful for cleanup functions}; } []));return <ProfileContent />;
}
Copy the code

You can also call the useIsFocused hook if you want to render different things based on whether the page is focused or not. UseIsFocused returns a Boolean value indicating whether the page is focused.

In general, the React lifecycle methods are still available, but React Navigation adds more event methods that developers can subscribe to via Navigation properties. Also, developers can hook using useFocusEffect or useIsFocused.

Nine, open a Modal full screen page

In RN, Model is a popover component. It is not a page in the navigation, so it has a unique way of showing and hiding it. We can use it to show some special prompts, as shown in the figure below.

9.1 Creating a Model Stack navigator

First, let’s take a look at the following code:

function HomeScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text style={{ fontSize: 30}}>This is the home screen! </Text> <Button onPress={() => navigation.navigate('MyModal')}
        title="Open Modal"
      />
    </View>
  );
}
 
function DetailsScreen(a) {
  return (
    <View>
      <Text>Details</Text>
    </View>
  );
}
 
function ModalScreen({ navigation }) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text style={{ fontSize: 30}}>This is a modal! </Text> <Button onPress={() => navigation.goBack()} title="Dismiss" />
    </View>
  );
}
 
const MainStack = createStackNavigator(a);const RootStack = createStackNavigator(a);function MainStackScreen(a) {
  return (
    <MainStack.Navigator>
      <MainStack.Screen name="Home" component={HomeScreen} />
      <MainStack.Screen name="Details" component={DetailsScreen} />
    </MainStack.Navigator>
  );
}
 
function RootStackScreen(a) {
  return (
    <RootStack.Navigator mode="modal">
      <RootStack.Screen
        name="Main"
        component={MainStackScreen}
        options={{ headerShown: false }}
      />
      <RootStack.Screen name="MyModal" component={ModalScreen} />
    </RootStack.Navigator>
  );
}
Copy the code

First, let’s look at a diagram of the navigator in the example above.In the example above, we used MainStackScreen as the screen component of the RootStackScreen, which is equivalent to embedding a stack navigator in another stack navigator. Therefore, when we run the project, the RootStackScreen renders a stack navigator with its own header, which we can also hide.

The stack navigator’s Model property value can be Card (the default) or Model. On IOS, the Model slides in from the bottom and closes from the top down when exiting. On Android, Model is an invalid property because the full-screen Model behaves no differently than the Android platform does.

The Model stack navigator is very useful in React Navigation. If you want to change the transition animation of the stack navigator page, you can use the Mode property. When set to Modal, the transition animation between all screen transitions will slide from the bottom to the top instead of sliding in from the right. Note, however, that React Navigation uses modal for the entire stack navigator, so to use the slide in from the right on other screens, we can add another navigator that uses the default configuration.

X. Name explanation

10.1 the Navigator

The Navigator is a React component that determines how the application will render the defined page. NavigationContainer, on the other hand, is a component that manages the navigation tree and contains the navigation state. This component is the parent container of all navigator components and wraps the structure of all navigators. In general, you need to place the NavigationContainer component in the root of your application as the root file for startup.

function App(a) {
  return (
    <NavigationContainer>
      <Stack.Navigator> // <---- This is a Navigator
        <Stack.Screen name="Home" component={HomeScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}
Copy the code

10.2 the Router

A Router is a Router, which is a set of functions that determine how user actions and state changes are handled in the navigator. In general, developers do not need to be directly involved in the Router interaction unless you need to write a custom navigator.

Each route is an object that contains a key identifying it and a “name” specifying the route type, and can also contain any type of parameter.

{
  key: 'B',
  name: 'Profile',
  params: { id: '123'}}Copy the code

10.3 Screen component

Screen Component is the Screen component that we need to jump to in routing configuration.

const Stack = createStackNavigator(a);const StackNavigator = (
  <Stack.Navigator>
    <Stack.Screen
      name="Home"
      component={HomeScreen} />
    <Stack.Screen
      name="Details"
      component={DetailsScreen} />
  </Stack.Navigator>
);
Copy the code

Note that the jump can only be implemented if the screen is rendered as a route by React Navigation. For example, if we render DetailsScreen as a child of the main screen, the DetailsScreen will not provide navigation items when you press “Go to Details…” on the main screen. The application throws an “undefined object” error when pressing the button.

function HomeScreen(a) {
  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Text>Home Screen</Text>
      <Button
        title="Go to Details"
        onPress={() => navigation.navigate('Details')}
      />
      <DetailsScreen />
    </View>
  );
}
Copy the code

10.4 Navigation Prop

We can pass data between two pages by using the properties provided by Navigation. Common properties are as follows.

  • Dispatch: Sends an action to the router.
  • Navigate, goBack: opens or returns to the page.

10.5 Navigation State

The status of the navigator is shown below.

{
  key: 'StackRouterRoot',
  index: 1,
  routes: [
    { key: 'A', name: 'Home' },
    { key: 'B', name: 'Profile']}},Copy the code