## React Native Route navigation, just have it! This document is translated according to the React Navigation document. Some contents will be explained according to your own understanding and literal translation will not be copied. If you find any problems with your understanding, please kindly comment! As I am based on iOS development, the Android version has not been put into practice yet. I will try it later when I have time. If you encounter any problems, please contact me. Finally, there is a summary of the problems encountered in the running of iOS, and provide solutions. Last but not least, we recommend a Chrome plugin that can automatically generate a table of contents from h1 to H6 in the article. It can also be used when writing the article. Smart TOC, click Install and operate as shown below:

The basic principle of

1 start

If you’re already familiar with React Native, you’ll be able to quickly get started with React navigation! If you haven’t studied React Native Express, you’ll need to read Parts 1-4 (including Part 4) and come back here.

The basics of this document cover the most important aspects of React navigation. It’s enough to give you an idea of how to build a typical small mobile application, and it gives you the background you need to dive into the more advanced parts of React navigation.

1.1 installation

Install the packages you need in your RN project

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

React navigation consists of a few core tools that the navigator uses to create navigation structures within the application. To pre-load the installation, we also need to install and configure most of the dependencies used by the navigator, and then we start writing the code.

Now, React-native Gear-handler, react-native Reanimated, react-native screens, react-native Safe-area-Context, etc. @react-native community/masked-view these libraries, if you have installed the latest version of these libraries, you can skip the following, otherwise read on.

1.2 Installation dependency toExpoManage the project

CD to your project directory and run:

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

This command installs the most appropriate versions of these libraries. Next, you can continue writing code in the project. (Note: I have never used Expo to manage projects before. If you have any questions, please check by yourself!)

1.3 Installation depends on native RN projects

CD to your project directory and run:

  • npm
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
  • yarn
yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
Copy the code

Note: Warnings about peer dependencies may appear after installation, usually due to different versions of packages, and should be ignored as long as your project is running smoothly.

Starting with RN 0.60 or later, these libraries automatically link projects, so there is no need to run the React-Native link.

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

When you’re done installing the react-native Gesture-handler, introduce the react-native Gesture-handler in the project’s entry file (such as index.js or app.js) (make sure it’s on the first line of the entry file)

import 'react-native-gesture-handler';
Copy the code

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

Now we need to load the entire app in NavigationContainer. The usual way to do this is in an entry file (such as index.js or app.js) :

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

Note: When you use a navigator (such as a stack navigator), you need to follow the navigator’s installation instructions for any other dependencies. If you encounter the “Unable to resolve module” error, you need to install the components prompted in the error into the project.

Now you can compile and run your project on a device or emulator and continue coding.

1.4 Problems encountered

TypeError: NULL is not an object (evaluating)'_RNGestureHandlerModule.default.Direction')
Copy the code

Solution: Add the following to your Podfile in ios folder:

pod 'RNGestureHandler', :path => ".. /node_modules/react-native-gesture-handler"
Copy the code

Terminal command CD to ios file, run pod install

2 Hello React Navigation

In a Web browser, you might use a tag to link to another page. When the user clicks a link, the URL is pushed into the browser history stack, and when the user clicks the back button, the browser pops up the previously visited page from the history stack as the current page. React Native doesn’t have the built-in concept of a global history stack like a Web browser does — that’s where the React navigation comes in.

React Navigation’s stack navigator provides an application with a way to convert and manage Navigation history between screens. If your application uses only one stack navigator, it is conceptually similar to how a Web browser handles navigation state — when a user interacts with it, your application pushes and pops items from the navigation stack, and the user can see different pages. One key difference in how it works in web browsers and React Navigation is that the React Navigation stack navigator provides the gestures and animations needed to navigate routes in the stack on Android and iOS.

Let’s start by demonstrating the most common navigator, createStackNavigator.

2.1 Installing the Stack Navigator library

So far we have installed the building blocks of the navigator and shared base libraries. Each navigator in React Navigation is in its own library. To use the stack navigator, we need to install @Response-navigation /stack:

  • npm
npm install @react-navigation/stack
Copy the code
  • yarn
yarn add @react-navigation/stack
Copy the code

Note: @react-navigation/stack relies on the library @react-native community/masked-view that we installed in the beginning section, if you haven’t installed it yet, please go back to the previous section.

2.2 Creating a stack navigator

CreateStackNavigator is a function that 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:

Navigationcomponent.js import React from navigationComponent.js import React from'react';
import {Text, View} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';

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

const Stack = createStackNavigator();

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

export default NavigationComponent;
Copy the code
// Introduce import in app.js'react-native-gesture-handler';
import React, {Component} from 'react';
import NavigationComponent from './Sections/ Common components /NavigationComponent';

export default class App extends Component {
  render() {
    return<NavigationComponent />; }}Copy the code

Try writing on Snack

Route names are case-insensitive — you can use lowercase home or uppercase HOME, depending on you. We like to capitalize route names.

The only configuration required for the screen is name and Component props. You can learn more about the other options available in the Stack Navigator Reference.

2.3 Configuring the Navigator

All routing configurations are specified as props for the navigator. We didn’t pass any props to the navigator, so it just uses the default configuration.

Let’s add a second screen to the stack navigator and configure the main screen to render first:

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

const Stack = createStackNavigator();

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

Try writing on Snack

Our stack now has two routing pages, a home page and a detail page. Routing can be specified using the Screen component. The screen component accepts a Name Prop, which corresponds to the name of the route to navigate, and a Component Prop, which corresponds to the component it will render.

Here, the main route corresponds to the HomeScreen component, while the detail route corresponds to the DetailsScreen component. The initial route of the stack is the primary route. Try changing it to Details and reload the application (as you might expect, React Native’s quick refresh doesn’t update the changes to initialRouteName), and notice that you now see the Details screen. Then change it to Home and reload it again.

Note: Component prop only accepts Component, not render functions. Do not pass inline functions (e.g. Component ={() =>}), or your component will unload and reload and remove all state when the parent component is re-rendered. See Passing Additional props instead.

2.4 specify the options

Each screen in the navigator can specify some options, such as the title of a render page. These options can be passed to the Options Prop for each screen component:

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

Try writing on Snack

Sometimes we want to specify the same options for all screens in the navigator. To do this, we can pass screenOptions Prop to the navigator.

2.5 pass props

Sometimes we might want to pass props to the screen. We can do this in two ways:

1. Wrap the navigator with the React Context provider to pass data to the screen (recommended).

2. Use screen render callbacks instead of specifying a prop for a component:

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

Note: By default, React Navigation optimizes screen components to prevent unnecessary rendering. Using render callbacks removes these optimizations. So if you use render callbacks, use react. memo or react. PureComponent for components to avoid performance issues.

2.6 Next Step?

The next question is: “How do I get from the main page to the details page?” , which will be covered in the next section.

2.7 summarize

  • React Native doesn’t have a built-in navigation API like a Web browser. The React navigation gives you this functionality, as well as gestures and animations for iOS and Android to switch between screens.
  • Stack.Navigator is a component that configures the route as a child component and is used to configure props and render the content.
  • Each stack.screen component accepts a name prop, which refers to the name of the route, and component Prop is specified as the component to be rendered by the route. These are the two required props.
  • To specify what the initial route in the stack is, set initialRouteName as a prop for the navigator.
  • To specify screen-specific options, we can pass an Options Prop to the stack. For common options, we can pass screen options to stack.navigator.

3 Screen switching

In the previous chapter, we define a contains the main page and details page stack routing, but we don’t have to learn how to let the user navigation home page and detail page (although we learned how to change the initial routing in your code, but let the user forced clone library and change the initial route, to show another page, you can imagine, this is the worst of the user experience).

For a Web browser, we could do this:

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

Another way is:

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

We’ll do something similar to the global window.location, we’ll use navigation Prop to pass down to the screen component.

3.1 Navigation to a new page

import 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

Try writing on Snack

Let’s break it down:

  • Navigation – In the stack navigator, the navigation property is passed to each screen component (defined). More on this later in the “In-depth Navigation Properties” section.
  • Navigate (‘Details’) – we call the navigational function with the name of the route to reach the page the user wants to see (on navigational properties – naming is difficult!) .

If we use navigation. Navigate to the route name that is not defined on the stack navigator, nothing will happen. In other words, we can only navigate to routes defined on the stack navigator — not to arbitrary components. We now have two routes on our stack :(1) the primary route and (2) the detailed route. What happens if we navigate to the details page again from the details page?

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

Try writing on Snack

If you run this code, when you click “Go to Details… Again “after won’t do anything! Because we’re already on the details page.

Suppose we do want to jump to a new detail page. This is very common when passing some unique data to each route (more on this later when we talk about parameters!). . We can do this with the push of navigate, which allows a route to be added regardless of whether it is on the stack.

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

Try writing on Snack

Each time you use push, a new route is added to the stack navigator. Navigate, on the other hand, checks whether there is a route with that name and jumps to a new route page when no route is on the stack.

3.2 return

In routing, there is a back button in the header of the current page, which can be clicked to return to the previous page (but if there is only one page in routing, the header does not have a back button and cannot operate the back button).

Sometimes you want to write code to do this, we use navigation.goback (); To do this:

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

Try writing on Snack

On Android, React Navigation returns the same event when the user clicks the hardware back button. Another common requirement is the return of multiple pages – for example, if you have jumped to multiple pages and want to go straight back to the first page, in this case we are returning Home, so we can use navigate(‘Home’)(instead of push! Try it and see the difference. Another option is navigation.poptotop (), which returns to the first screen in the stack.

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

Try writing on Snack

3.3 summarize

  • Navigation.navigate (‘RouteName’) if the new route is not on the stack, push it to the stack navigator or jump to this page.
  • Navigation. Push (‘RouteName’) can jump to the same routing page multiple times.
  • The header bar comes with a return button to provide the return operation, but we can use navigation.goback () to do that. The hardware back button on Android works the same way.
  • You can return to an existing page using navigation.navigate(‘RouteName’), and you can return to the first page using navigation.poptotop ().
  • Navigation properties can be obtained in all page components (as long as the component is defined to route configuration and render routes using React Navigation).

4 Transfer parameters between routes

Remember I said “I’ll talk more about this later when WE talk about parameters! “? Now you can start.

Now that we know how to create some routes on the stack navigator and jump between routes, how to pass parameters between routes, let’s see.

There are two parts:

  1. Place the required parameters of the route in an object as the second parameter of the navigation.navigate function:navigation.navigate('RouteName', { /* params go here */ })
  2. Get this parameter in the component:route.params.

We recommend passing the parameters in JSON format. This way, you can use state persistence, and your screen components can use the right conventions to implement deep linking.

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>
  );
}
Copy the code

Try writing on Snack

4.1 Updating Parameters

Parameters can also be updated on the page, similar to updating the page status. Navigation. SetParams can be used to update page parameters. Learn more through API Reference for.

You can also pass some initial parameters to the page. If you navigate to the page without setting any parameters, this initial parameter will be used. They are shallow merged with the passed parameters. The initial parameter is specified as the initialParams property:

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

4.2 Pass parameters to previous pages

You can pass parameters not only to the new page, but also to the previous page. For example, create a POST button on a page, and click the button to create a new POST page. After you create a POST page, you want to pass some data to the previous page.

To do this, you can use the navigate method or, if the page exists, a method like goBack. You can return the parameter with the navigate parameter:

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]);

  return (
    <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
      <Button
        title="Create post"
        onPress={() => navigation.navigate('CreatePost', { text: route.params? .post ? route.params? .post :' ', })} /> <Text style={{ margin: 10 }}>Post: {route.params? .post}</Text> </View> ); }functionCreatePostScreen({navigation, route}) {// Pass the input to the TextInput processing logiclet {text} = route.params;
  let [postText, setPostText] = React.useState(text);

  return (
    <>
      <TextInput
        multiline
        placeholder="What's on your mind?"
        style={{ height: 200, padding: 10, backgroundColor: 'white' }}
        value={postText}
        onChangeText={setPostText}
      />
      <Button
        title="Done"
        onPress={() => {
          // Pass params back to home screen
          navigation.navigate('Home', { post: postText }); }} / > < / a >); }Copy the code

Try writing on Snack

When the “Done” button is clicked, TextInput’s input is returned to the home page and refreshed.

4.3 Nested navigation pages pass parameters

If you have a nested navigator, the passing parameters are slightly different. For example, you have a page called Account and want to pass parameters to the Settings page. You need to perform the following operations:

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

Click on Nesting Navigators to learn more

4.4 summarize

  • Navigate and push can be passed as an optional second parameter when navigating the page. Such as:navigation.navigate('RouteName', {paramName: 'value'}).
  • You can pass it on the pageroute.paramsRead the parameters passed.
  • Can be achieved bynavigation.setParamsUpdate page parameters.
  • throughinitialParamsProperty can pass initialized parameters.

5 Configure header Bar

We already know how to configure header headers, but let’s review them one more time before we look at the other options — review is the key to learning

5.1 Setting the Header Title

The component accepts options Prop, which is an object or a function that returns an object and contains various configuration options. One of these is title, as shown in the following example:

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

Try “Header title” on Snack

5.2 Using Parameters in Title

To use parameters in title, we need to set up a function for the page that returns a configuration object. It is useful to try to use this.props in options, but there is no instance of the component referenced before the component is rendered, so there is no props available. In contrast, if we set options to a function, React Navigation will call it with an object containing {Navigation, route} — in this case, what we care about is route, It is the same object that was passed to the page Prop as a Route Prop. Remember we can get parameters by route. Parameter, now we use this to extract the parameter and use it as the title.

function StackScreen() {
  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

Try “Params in Title” on Snack

The argument passed to the option function is an object with the following properties:

  • Navigation – Page Navigation prop
  • Route-page Route Prop

In the example above we only need the route property, in some cases we also need the navigation property.

5.3 Updating options with setOptions

You usually need to update the options configuration for the active page in the installed screen component itself. We can do this using navigation. SetOptions.

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

Try “Updating Navigation Options” on Snack

5.4 Adjusting the Header Style

Custom header style has three key attributes: headerStyle, headerTintColor, and headerTitleStyle.

  • HeaderStyle: The style object applied to the view that wraps the header. If you set its backgroundColor, you set the header color.
  • HeaderTintColor: Both the back button and the title use this property as the font color. In the example below, we set the hue to white (# FFF) so that the return button and title title are white.
  • HeaderTitleStyle: Use it to customize fontFamily, fontWeight, and other text styles.
function NavigationComponent() {
  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

Try “header styles” on Snack

Note:

  1. On iOS, the font and icon on the status bar are black, which isn’t very friendly to display on a dark background, and we won’t discuss it here, but you should make sure to configure the status bar to fit the color the status bar guides your screen.
  2. We only configure these on the main page, and when we jump to the details page, the header reverts to its original style. Next, let’s look at sharing styles between pages.

5.5 Sharing Options between pages

Typically, we’ll set a header with the same style on multiple pages. For example, say your company brand color is red, and the page header wants to have a red background and white font. In the example above, we configured the color of the home header, and when we jump to the details page, the header reverts to its default style. It would be a hassle if we copied the home page style configuration to the details page, but what if every page in the app needed that style? Instead of doing this, we can move the style configuration to the screenOptions property under Stack.Navigator.

function StackScreen() {
  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

Try “Sharing header Styles” on Snack

Now, pages belonging to StackScreen all have a theme style, but what if we need to override these configurations?

5.6 Replacing headings with custom components

Sometimes you want to do more than just change the text and style of the title — for example, you want to replace the title with a picture, or set the title to a button. In these cases, you can simply override the title using a custom component.

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

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

Try “Custom Header Title Component” on Snack

You may have noticed why we set headerTitle as a component instead of title as before? Since headerTitle is a property of stack. Navigator, headerTitle is a Text component by default that displays title.

5.7 Additional Configuration

You can browse the list of configurations in the StackNavigator in the createStackNavigator Reference.

5.8 summarize

  • You can customize the header style of the page using the properties in options. Read all options in the API reference.
  • Options can be an object or a function. When used as a function, it provides an object containing the navigation and route properties.
  • At initialization, a shared style can be configured through screenOptions. This attribute takes precedence over configuration.

6 Header buttons

Now that we know how to define the header’s appearance, we might be more motivated to customize the configuration in response to the user’s touch.

6.1 Adding a Button to the header

Most interactions on headers have a button on the left or right that you can click. Let’s add a button to the right of the header (this is one of the hardest places to touch on the entire screen, depending on the size of your finger and phone, but is the normal place to put a button).

function StackScreen() {
  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

Try “Header Button” on Snack

When we define the button through this method, since it is not a variable option of the HomeScreen instance, we cannot change it using setState or any other instance method. This is important because it is very common to add button interactions to headers. So let’s see what we can do.

6.2 Header interaction with page components

To be able to interact with page components, we define the button using navigation. SetOptions instead of the options property. With navigation. SetOptions in the page component, we can access the props, state, context, etc.

function StackScreen() {
  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 title="Update count!" onPress={() => setCount((c) => c + 1)} />
      ),
    });
  }, [navigation, setCount]);

  return <Text>Count: {count}</Text>;
}
Copy the code

Try “Header Interaction” on Snack

6.3 Customizing the Return button

CreateStackNavigator provides a default Back button for a specific platform. On iOS, it contains button and Text, which displays the title of the previous page in the available space, otherwise only the Back content is displayed.

You can modify the behavior of a label with headerBackTitle and headerTruncatedBackTitle (more).

You can use headerBackImage to customize the image of the return button.

6.4 Override the back button

As long as the user can return to the previous page from the current page, the back button is automatically rendered to the stack navigator — in other words, as long as there is more than one page on the stack, the back button is automatically rendered.

In general, that’s what you want. But in some cases, you might prefer to customize the back button rather than through the options mentioned above, in which case you can set the headerLeft option to the React element that will be rendered, just as we did with headerRight. In addition, the headerLeft option also accepts a React component, which you can use to override the onPress behavior of the back button, for example. See API Reference for more information.

6.5 summarize

  • You can set buttons on the header using the Options properties headerLeft and headerRight.
  • The back button can be fully customized using headerLeft, but if you just want to change the title and image, there are other properties you can set –headerBackTitle, headerTruncatedBackTitle, and headerBackImage.

7 Nested navigation

Nested navigation means rendering another navigation within a page on one navigation, for example:

Install the required library of components using @react-navigation/bottom-tabs:

  • npm
npm install @react-navigation/bottom-tabs
Copy the code
  • yarn
yarn add @react-navigation/bottom-tabs
Copy the code

Then we begin our coding:

/* Customize the NestingNavigators. Js file to app.js */ import React from'react';
import {Text, View, Button} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';

function Feed() {
  return (
    <View
      // eslint-disable-next-line react-native/no-inline-styles
      style={{
        flex: 1,
        backgroundColor: '#e3e',
        justifyContent: 'center',
        alignItems: 'center',
      }}>
      <Text>Feed Screen</Text>
      <Button
        title="Go to Profile"
        onPress={() => navigation.navigate('Profile')}
      />
    </View>
  );
}

function Messages() {
  return (
    <View
      // eslint-disable-next-line react-native/no-inline-styles
      style={{
        flex: 1,
        backgroundColor: '#b33',
        justifyContent: 'center',
        alignItems: 'center',
      }}>
      <Text>Messages Screen</Text>
    </View>
  );
}

const Tab = createBottomTabNavigator();

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

function Profile() {
  return (
    <View
      // eslint-disable-next-line react-native/no-inline-styles
      style={{
        flex: 1,
        backgroundColor: '#a3e',
        justifyContent: 'center',
        alignItems: 'center',
      }}>
      <Text>Profile Screen</Text>
    </View>
  );
}

function Settings() {
  return (
    <View
      // eslint-disable-next-line react-native/no-inline-styles
      style={{
        flex: 1,
        backgroundColor: '#e3a',
        justifyContent: 'center',
        alignItems: 'center',
      }}>
      <Text>Settings Screen</Text>
    </View>
  );
}

const Stack = createStackNavigator();

function NestingNavigators() {
  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>
  );
}

export default NestingNavigators;
Copy the code

(Note: the official document code omitted a lot, I got a complete here, interested in children’s shoes can also achieve their own!)

In the example above, the Home component contains a TAB navigation. Throughout the App component, the Home component is also used on the Home page of the Stack navigation. Therefore, the TAB navigation is nested inside the stack navigation:

* Stack. The Navigator. Home (tab.navigator).feed (Screen).Messages (Screen). Profile (Screen). Settings (Screen)Copy the code

Nested navigators work much like nested regular components. To achieve the behavior you want, you often need to nest multiple navigators.

7.1 What is the Impact of nested navigation

There are a few things to look out for when nesting navigation:

7.1.1 Each navigator saves its own navigation history

For example, clicking the back button in a nested stack navigation will return you to the previous page in the nested stack, even if there is another navigator as the parent view.

7.1.2 Navigation operations are handled by the current navigator or, if not, by its parent navigator

For example, if you call navigation.goback () on a nested page, it will only return to the parent navigation if it is already on the first page. Other operations, such as navigate, have the same effect. For example, a nested navigate operation that is not handled will then be handled by the parent navigation. In the above example, when navigate(‘Messages’) is called on the Feed page, the nested TAB navigation handles it, but if you call navigate(‘Settings’), the parent stack navigator handles it.

7.1.3 Nested navigation does not receive parent events

For example, if you have a stack navigation nested within a TAB navigation, pages on the stack navigation will not receive notification events from the parent TAB navigation, such as adding navigation. AddListener when (tabPress). In order to receive the parent navigation events, you can use the navigation. DangerouslyGetParent (). The addListener to listen to the father.

7.1.4 UI rendering of the parent navigation is at the top of the child navigation

For example, when nesting a stack navigation into the fold (drawer) navigation, you will see the fold page at the head of the stack navigation. However, if you nest a collapsed navigation into the stack navigation, the collapsed page will appear under the header. This is an important point for you to decide how to nest navigation.

In your App, you might use these patterns depending on the behavior you want:

  • The stack navigation is nested within each page of the collapsed navigation – the collapsed page appears above the header of the stack.
  • The Tab navigation is nested in the initial page of the stack navigation – when the page is pushed, the new page overwrites the Tab bar.
  • Stack navigation is nested within each page of TAB navigation – TAB bar is always visible. Clicking TAB will pop again to the top of the stack.

7.2 Navigating to a page in a nested navigation

Consider the following example:

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

const Drawer = createDrawerNavigator();

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

Here, you might want to navigate from the Home page to the Root stack page:

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

This is fine. The initial page in the Root component will display, yes, the Profile. But sometimes, you might want to control the page you want to display in the navigation. You can specify the page name in the parameters by doing the following:

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

Settings will now be displayed in the navigation instead of profiles.

This may look very different from previous navigation using nested pages. The difference is that all configurations are static, so React Navigation can find a list of all navigators and their pages statically by recursing into a nested configuration. But with dynamic configuration, React Navigation doesn’t know which pages are available and where until the navigator contains the page rendering. In general, the contents of a page are not rendered until the page has been navigated, so the configuration of a navigator that has not been rendered is not available. This requires specifying the hierarchy to navigate to. This is why you should use as little navigation nesting as possible to make your code simpler.

7.2.1 Pass parameters to pages in nested navigation

You can also pass arguments with a specified key:

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

Try writing on Snack

If the navigation is rendered, jumping to another page when using stack navigation pushes you to a new page.

A similar approach can be used for deeply nested screens. Notice that the second parameter of navigate, params, can also do this:

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

In the example above, you want to navigate to the Media page, which is nested inside the Sound page, which is nested inside the Settings page.

7.2.2 Render the defined initial route in the navigator

By default, when navigating to a page nested in the navigation, the specified page is used for the original page and the initial route attributes are ignored. This is different from React Navigation 4.

If you want to render a specified initial page in the navigation, you can disable the behavior of using the specified page as the initial page by setting initial: false:

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

7.3 Best practices for Nesting

We recommend minimizing nested navigation. Try to implement the behavior you want with as little nesting as possible. There are many disadvantages to nesting:

  • When navigating to nested pages, the code becomes incomprehensible
  • It can lead to deeply nested view hierarchies, which can cause memory and performance problems on low-end devices
  • Nesting navigators of the same type (such as TAB in TAB, drawer in drawer, and so on) can lead to a confusing user experience.

Think of nested navigators as a way to achieve the UI you want, not as a way to organize your code. If you want to create separate groups of pages for your organization, save them in separate objects/arrays rather than in separate navigators.

8 Navigation Life cycle

In the previous section, I manipulated a stack navigation with the Home and Details pages and used navigation.navigate(‘RouteName’) to navigate between routes.

An important question in this regard is: what happens when we leave or return to the Home page? How does the user know to leave or return to a routing page?

If you look at react navigation from a Web perspective, you can assume that when the user navigates from route A to route B, A will be unloaded (componentWillUnmount is called) and loaded again when returned to A. While these React lifecycle methods are still valid and used in act-Navigation, their usage is different from that of the Web. This is driven by more complex mobile navigation requirements.

8.1 Example Scenario

There is A stack navigation with pages A and B. After navigating to the A page, its componentDidMount function is called. When pushed to the B page, its componentDidMount is also called, but A is still mounted on the stack, so its componentWillUnmount is not called.

When returning to A from page B, componentWillUnmount for page B is called, but componentDidMount for Page A is not called because A stays on the stack for the entire life cycle.

Similar results can be observed in combination with other navigators. Consider a TAB navigation with two tabs, each on the stack navigation:

/* Navigation lifecycle */ import React from'react';
import {Text, View, Button} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'; / * here is omitted, reduce length, specific code can find * / in the previous codefunction Profile() {... }function Settings() {... }function HomeScreen() {... }function DetailScreen() {... } const Tab = createBottomTabNavigator(); const SettingsStack = createStackNavigator(); const HomeStack = createStackNavigator();function NavigationLifeCycle() {
  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen name="First">
          {() => (
            <SettingsStack.Navigator>
              <SettingsStack.Screen name="Settings" component={Settings} />
              <SettingsStack.Screen name="Profile" component={Profile} />
            </SettingsStack.Navigator>
          )}
        </Tab.Screen>
        <Tab.Screen name="Second">
          {() => (
            <HomeStack.Navigator>
              <HomeStack.Screen name="Home" component={HomeScreen} />
              <HomeStack.Screen name="Details" component={DetailScreen} />
            </HomeStack.Navigator>
          )}
        </Tab.Screen>
      </Tab.Navigator>
    </NavigationContainer>
  );
}

export default NavigationLifeCycle;
Copy the code

Try writing on Snack

Start at HomeScreen, then navigate to the DetailsScreen. Then switch to TAB to display the SettingsScreen page and navigate to ProfileScreen. This part of the operation is complete, all four pages have loaded! If you TAB back to HomeStack, you will see the DetailsScreen page -HomeStack has saved the navigation state.

8.2 React Navigation lifecycle events

Now that we have seen how the React lifecycle method works in React Navigation, let’s answer the initial question: “How does the user know when to blur or focus back to a routing page?” “

React Navigation emits events to page components that subscribe to events. We can listen for focus and blur events to see if the current page is in or out of the current page.

Such as:

function Profile({navigation}) {
  React.useEffect(() => {
    const unsubscribe = navigation.addListener('focus', () => {
      //Screen was focused
      //Do sometings
      console.log('Profile page is focused!!! ');
    });
    return unsubscribe;
  }, [navigation]);
  return (
    <View
      // eslint-disable-next-line react-native/no-inline-styles
      style={{
        flex: 1,
        backgroundColor: '#a3e',
        justifyContent: 'center',
        alignItems: 'center',
      }}>
      <Text>Profile Screen</Text>
    </View>
  );
}
Copy the code

Try writing on Snack

See Navigation Events for more information on events and API usage

Instead of manually adding event listeners, we can do this using useFocusEffect. It is similar to the React useEffect, but it is closely tied to the navigation lifecycle.

Such as:

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

function Profile({navigation}) {
  useFocusEffect(
    React.useCallback(() => {
      //Do something when the screen is focused
      console.log('Profile page is focused!!! ');
      return () => {
        //Do something when the screen is unfocused
        // Useful for cleanup functions
        console.log('Profile page is unfocused!!! '); }; }, []));return (
    <View
      // eslint-disable-next-line react-native/no-inline-styles
      style={{
        flex: 1,
        backgroundColor: '#a3e',
        justifyContent: 'center',
        alignItems: 'center',
      }}>
      <Text>Profile Screen</Text>
    </View>
  );
}
Copy the code

Try writing on Snack

If you want to render different things depending on whether the page is focused or not, you can use useIsFocused, which returns a Boolean value indicating whether the page is focused or not.

8.3 summarize

  • While the React lifecycle method is still in effect, the React navigation adds more events that can be subscribed to via the Navigation property.
  • You can also use useFocusEffect or useIsFocused instead.

9 Turn on full-screen mode

The modal displays the content that temporarily interacts with the main view.

A mode is like a popbox — it’s not part of your main navigation flow — and it usually has a different transition, different method dismiss it, and focus on a particular content or interaction.

The purpose of explaining this as part of React Navigation fundamentals is not only because it is a common use case, but also because it requires knowledge of nested navigators to implement, which is an important part of React Navigation.

9.1 Creating a Modal stack

/* Navigation lifecycle */ import 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 (
    // eslint-disable-next-line react-native/no-inline-styles
    <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}> <Text style={{fontSize: 30}}>This is the home screen! </Text> <Button title="Open Modal"OnPress ={() => /* 1. Pass parameters to the details page */ navigation.navigate('MyModal')
        }
      />
    </View>
  );
}

function DetailScreen() {
  return (
    // eslint-disable-next-line react-native/no-inline-styles
    <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
      <Text>Detail Screen</Text>
    </View>
  );
}

function ModalScreen({navigation}) {
  return (
    // eslint-disable-next-line react-native/no-inline-styles
    <View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}> <Text style={{fontSize: 30}}>This is a Modal! </Text> <Button title="Dismiss" onPress={() => navigation.goBack()} />
    </View>
  );
}

const MainStack = createStackNavigator();
const RootStack = createStackNavigator();

function MainStackScreen() {
  return (
    <MainStack.Navigator>
      <MainStack.Screen name="Home" component={HomeScreen} />
      <MainStack.Screen name="Details" component={DetailScreen} />
    </MainStack.Navigator>
  );
}

function NavigationModal() {
  return (
    <NavigationContainer>
      <RootStack.Navigator mode="modal">
        <RootStack.Screen
          name="Main"
          component={MainStackScreen}
          options={{headerShown: false}}
        />
        <RootStack.Screen
          name="MyModal"
          component={ModalScreen}
          options={{headerShown: false}}
        />
      </RootStack.Navigator>
    </NavigationContainer>
  );
}

export default NavigationModal;
Copy the code

(Note: there are some problems with the code provided in the official document, I have improved it.)

Try writing on Snack

Some important things to note:

  • We use the MainStackScreen component as a page for the RootStackScreen! Here, we’re nesting one stack navigation inside another stack navigation. This is perfectly valid because we want to use the modes to achieve different transitions. Since the RootStackScreen renders a stack navigator and has its own header, we also want to hide the header for this page. It will be important in the future for TAB navigation, for example, each TAB will have its own stack. Intuitively, this is what you expect: When you switch from TAB A to TAB B, you want TAB A to remain in its navigational state as you continue browsing TAB B. In this example, you can see the structure of the navigation:

  • On the stack navigation, the mode attribute can be: card (default) and modal. On iOS, modal’s behavior swipes the screen from the bottom and allows the user to swipe down from the top to close it. The modal attribute has no effect on Android because full-screen mode doesn’t have any different conversion behavior on the platform.

  • When we call navigate, we do not need to specify anything other than the route to which we want to navigate. There is no need to qualify which stack it belongs to (arbitrarily named “root” or “main” stack) — the React navigation tries to find the route on the nearest navigator and then perform operations there. To visualize this, look again at the tree diagram above and imagine the Navigate action flowing from the main screen to the main stack. We know MainStack can’t handle the route MyModal, so it streams it to RootStack, which can handle that route, so it does.

9.2 summarize

  • To change the transition mode on the stack navigation, use the mode property. When set to Modal, all screens are dynamic — from bottom to top instead of right to left. This applies to the entire stack navigator, so in order to use right-to-left transformations on other pages, we add another navigation stack with the default configuration.

  • Navigate through the navigator tree to find navigators that can handle navigation operations.

10 Glossary

This is a new part of the document, missing a lot of terminology! Please submit a pull request or a terminology question that you think should be explained here.

10.1 the Header

Also called navigation header, Navigation bar, Navbar, and possibly many more. This is the rectangle at the top of the screen that contains the back button and the screen title. The entire rectangle is usually called a header in React Navigation.

10.2 the Navigator

The navigator contains the Screen element as its child to define the configuration of the route. NavigationContainer is the component that manages the navigation tree and contains the navigational state. This component must wrap all navigator structures. Normally, we would render this component in the root directory of the application, usually exported from app.js.

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

10.2 Screen component

The screen component is the component we use in routing configuration.

const Stack = createStackNavigator();

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

The suffix Screen in component names is entirely optional, but is a commonly used convention. We could call it Michael, and it works the same way.

As we saw earlier, our screen component comes with the navigation Prop. It is important to note that this only occurs when the screen is rendered as a route by React Navigation (for example, in response to navigation.navigate). For example, if we present DetailsScreen as a child of HomeScreen, the DetailsProperty will not be supplied with the navigation prop, and when you press “go to Details again…” on the HomeScreen. Button, the application will throw a typical JavaScript exception “undefined is not an object”.

function HomeScreen() {
  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

The “Navigation Prop Reference “section covers this in more detail, describes the workaround, and provides more information about other properties available on the Navigation Prop.

10.3 Navigation Prop

This prop is passed to all pages and can be used for the following purposes:

  • Dispatch sends an action to the router
  • Navigate, goBack, etc. can be used to schedule operations in a convenient manner

Navigators can also accept navigation prop, if any, they should be obtained from the parent navigator.

Please refer to “Navigation Prop Document “for more details.

The “Route Prop Reference “section covers this in more detail, describes the workaround, and provides more information about other properties available on routing Prop.

10.4 the Route prop

The prop will be passed to all pages. Contains information about the current route, that is, parameters, key, and name.

10.5 Navigation State

The state of the navigator is usually as follows:

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

For this navigational state, there are two routes (which can be tabs or cards in the stack). The index points to the active route, which is “B”.

10.6 the Route

Each route is a navigational state with a key to identify it and a “name” to specify the route type. It can also contain arbitrary arguments:

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

11 compatibility layer

Note: Before following this guide, make sure you have set React Navigation 5 in your application as per the getting Started guide.

React Navigation 5 has a brand new API, so the old code we used with React Navigation 4 will no longer work with this release. If you are not familiar with the new API, you can read the differences in the upgrade guide. We knew this could be a lot of work, so we created a compatibility layer to simplify the process.

To use this compatibility layer, install @react-Navigation /compat:

  • npm
npm install @react-navigation/native @react-navigation/compat @react-navigation/stack
Copy the code
  • yarn
yarn add @react-navigation/native @react-navigation/compat @react-navigation/stack
Copy the code

Then we’ll make a few small changes in our code:

// "-" means delete, "+" means add -import {createStackNavigator} from'react-navigation-stack';
+import { createStackNavigator } from '@react-navigation/stack';
+import { createCompatNavigatorFactory } from '@react-navigation/compat';
-const RootStack = createStackNavigator(
+const RootStack = createCompatNavigatorFactory(createStackNavigator)(
  {
    Home: { screen: HomeScreen },
    Profile: { screen: ProfileScreen },
  },
  {
    initialRouteName: 'Profile'});Copy the code

Import @react-navigation/compat:

// "-" means delete, "+" means add -import {NavigationActions} from'react-navigation'; 
+import { NavigationActions } from '@react-navigation/compat';
Copy the code

The library exports the following apis:

  • Actions: -> NavigationActions -> StackActions -> DrawerActions -> SwitchActions
  • HOCs -> withNavigation -> withNavigationFocus
  • Navigators -> createSwitchNavigator
  • Compatibility helpers – > createCompatNavigatorFactory – using the v5 API navigator, and USES the API return createXNavigator v4. – > createCompatNavigationProp – v5 object of navigation and route objects are used together, and return the v4 navigator object.

11.1 What does it handle?

The compatibility layer handles various API differences between React Navigation 4 and 5:

  • Use v4’s static configuration API instead of the component-based API.
  • Change the signature of the method on the navigation object to match V4.
  • Added support for screenProps removed in version 5.
  • Export the action creator, such as NavigationActions, StackActions, SwitchActions, with the same signature as V4.

11.2 What does it not handle?

Due to React Navigation 5’s dynamic API, v4’s static API no longer has certain features, so the compatibility layer cannot handle them:

  • It does not wrap prop or options for the navigator. Basically, this means that the options you pass to the navigator can vary depending on major changes in the navigator. Refer to the navigator’s documentation for the update option API.
  • Support for old-style deep linking by defining a path in the routing configuration is not supported. See Deep Linking Documentation for more details on how deep links are now handled.
  • Navigation to the navigator works differently, that is, we cannot navigate to screens in the navigator that have not yet been rendered, and we cannot merge parameters into all sub-screens. For more details on how to navigate to screens in other navigators, see the nested navigator documentation.
  • Some methods that take a series of actions, such as the old reset method, are no longer supported. Unsupported methods throw errors when using them, or type errors if we’re using TypeScript.
  • It does not export createAppContainer, so you need to use the V5 API for the container (NavigationContainer). This also means that all functions supported by the container need to be migrated to the new API.
  • If you are using advanced apis such as Redux integration, custom routers, and operations that are no longer supported, you need to remove the Redux integration.

Although we have done our best to make the compatibility layer handle most of the differences, some things may be lost. Therefore, be sure to test the migrated code.

Why should we use it?

Using the compatibility layer allows us to gradually migrate code to the new version. Unfortunately, we did have to change some code for the compatibility layer to work properly (see “What it doesn’t handle”), but it still allowed most of our code to stay the same. Some advantages of using a compatibility layer include:

  • It allows you to write new code using the new API while integrating with the code using the old API, that is, you can navigate from code written in the new API to a screen defined in the old API, and vice versa.
  • Because it builds on V5 with excellent TypeScript support, older code can also take advantage of improved type-checking, which can be useful later when you want to refactor it into a new API.
  • You can look at the migration in detail, such as migrating only a few methods in a component to a new API. You still have access to the V5 navigation object on Navigation. original, which can be used to migrate code step by step.
  • You can access new apis in older components, such as navigation.setoptions or new hooks, such as useFocusEffect.

We are committed to helping you make the upgrade as easy as possible. Therefore, ask questions about use cases not supported by the compatibility layer so that we can figure out a good migration strategy.

12 Troubleshooting

This section attempts to outline the common problems that users encounter when first getting used to using React Navigation. These issues may or may not be related to React Navigation itself.

Before resolving the problem, ensure that you have upgraded to the latest available version of the software package. You can install the latest version by installing the package again (for example, NPM install package-name).

12.1 The Unable to Resolve module error occurs when the latest version is updated

There are three reasons:

Outdated cache for Metro bundler

If the module points to a local file (that is, the module name starts with a./), it may be due to an outdated cache. To solve this problem, try the following solution.

If using Expo, run:

expo start -c
Copy the code

If you’re not using Expo, run:

npx react-native start --reset-cache
Copy the code

If nothing works, perform the following operations:

rm -rf $TMPDIR/metro-bundler-cache-*
Copy the code

12.2 Lack of Peer Dependency

If the module points to an NPM package (that is, the module name does not have a./), this may be due to a lack of peer dependencies. To resolve this issue, install dependencies in your project:

  • npm
npm install name-of-the-module
Copy the code
  • yarn
yarn add name-of-the-module
Copy the code

Sometimes it can even be caused by installation damage. If clearing the cache doesn’t work, try deleting your node_modules folder and then running NPM Install again.

12.3 No extension is displayed in Metro Configuration

Sometimes an error is reported like this:

Error: While trying to resolve module "@react-navigation/native" from file "/path/to/src/App.js", the package "/path/to/node_modules/@react-navigation/native/package.json" was successfully found. However, this package itself specifies a "main" module field that could not be resolved ("/path/to/node_modules/@react-navigation/native/src/index.tsx"
Copy the code

This can happen if you have a custom configuration for Metro and do not specify TS and TSX as valid extensions. These extensions exist in the default configuration. To check for this problem, look for the metro.config.js file in your project and check that the sourceExts option is specified. It should have at least the following configuration:

sourceExts: ['js'.'json'.'ts'.'tsx'];
Copy the code

If these extensions are missing, add them, and then clear the Metro cache as shown in the previous section.

12.4 Error “SyntaxError in @react-navigation/ XXX /xxx.tsx” or “SyntaxError: / XXX /@react-navigation/ XXX /xxx.tsx: Unexpected token”

This can happen if you are using an older version of the Metro-React-native Babel-Preset package. The easiest way to fix it is to remove node_modules and lock the file and reinstall the dependencies.

If NPM is used:

rm -rf node_modules
rm package-lock.json
npm install
Copy the code

If yarn is used:

rm -rf node_modules
rm yarn.lock
yarn
Copy the code

You may also want to clear Metro Bundler’s cache as described earlier on this page.

12.5 Error “Module ‘[…] ‘has no exported member’ XXX ‘when using TypeScript”

This can happen if you have older versions of TypeScript in your project. You can try to upgrade it:

If NPM is used:

npm install --save-dev typescript
Copy the code

If yarn is used:

yarn add --dev typescript
Copy the code

12.6 error “null is not an object (evaluating RNGestureHandlerModule. Default. ‘Direction’)”

This error and similar errors can occur if you do not link the React-Native Mouth-Handler library.

Automatic linking starts with React Native 0.60, so if you manually link to the library, please unlink first:

react-native unlink react-native-gesture-handler
Copy the code

If you want to test and use Mac on iOS, make sure you have pod Install running in the iOS/folder:

cd ios
pod install
cd.Copy the code

Now, recompile the app and test it on your device or emulator.

12.7 Nothing Is Displayed After A View Is Added

If you wrap a container inside a View, be sure to use Flex: 1 to stretch the View to fill the container.

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

export default function App() {
  return (
    <View style={{ flex: 1 }}>
      <NavigationContainer>{/* ... */}</NavigationContainer>
    </View>
  );
}
Copy the code

12.8 warning: “Non-serializable values were found in the navigation State”

This can happen if you pass non-serializable values in arguments, such as class instances, functions, and so on. React Navigation warns you in this case, as this may break other features such as state persistence, deep linking, etc.

Examples of common use cases for passing functions in parameters are as follows:

  • Pass the callback to use in the title button. You can use navigation. SetOptions instead. For examples, see Guide for Header buttons.
  • Pass the callback to the next screen, which can be called to pass some data back. Typically, you can do this using navigation. For examples, see Guide for Params in the guide.
  • Transfer complex data to another screen. Instead of passing data parameters, you can store the complex data in another location (such as global storage) and pass an ID. The screen can then use the ID to retrieve data from the global store.

If you don’t use state persistence or deep linking of screens that take the form of parameters, the warning doesn’t affect you and you can safely ignore it. To ignoreWarnings, use yellowbox.ignorewarnings.

Such as:

import { YellowBox } from 'react-native';

YellowBox.ignoreWarnings([
  'Non-serializable values were found in the navigation state',]);Copy the code

12.9 An Application Fails to Run Properly After I Connect to the Chrome Debugger

When your application connects to the Chrome Debugger (or any other tool that uses the Chrome Debugger, such as React Native Debugger), you may encounter various issues related to timing.

This can lead to problems such as buttons that take a long time to register or don’t work at all, gestures and animations that are slow and error-prone. There may be other feature issues, such as Promises that won’t be resolved, timeouts and intervals that won’t work. Is the same

These issues are not related to React Navigation, but are due to how the Chrome debugger works. Once connected to the Chrome debugger, your entire application will run on Chrome and communicate with native applications over sockets on the network, which can cause latency and times-related issues.

Therefore, unless you are trying to debug, it is best to test the application without connecting to the Chrome debugger. If you’re using iOS, you can debug the application using Safari, which can debug the application directly on the device without these problems, although it has other drawbacks.

13 limitations

As a potential user of the library, it is important to know that you can and cannot use it. Armed with this knowledge, you can choose a different library instead. We will discuss high-level design decisions in Pitch & Anti-Pitch, where we will introduce use cases that are either not supported or are so difficult to accomplish that they are impossible. If any of the following restrictions are a wrecker of your application, React Navigation may not be for you.

13.1 Limited right-to-left (RTL) layout support

We are trying to handle the RTL layout correctly in React Navigation, but the team working on React Navigation is small and we currently don’t have the bandwidth or process to test all changes to the RTL layout. Therefore, you may encounter RTL layout problems.

If you like what React Navigation has to offer but are turned off due to this limitation, we encourage you to get involved and take ownership of RTL layout support. Contact us on Twitter: @reactNavigation.

13.2 Some platform-specific behaviors

React Navigation does not support the peeping and popup features available on devices with 3D touch capabilities.

RN routing -React Navigation- Tab Navigation

Refer to the document: React Navigation – Fundamentals