This is the 10th day of my participation in the August More Text Challenge. For details, see:August is more challenging

Properties in options:

  • Public Settings across pages

    <Stack.Navigator
          screenOptions={{
            headerStyle: {
              backgroundColor: '#f4511e',},headerTintColor: '#fff'.headerTitleStyle: {
              fontWeight: 'bold',}}} ><Stack.Screen
            name="Home"
            component={HomeScreen}
            options={{ title:}} />
        </Stack.Navigator>
    Copy the code
  • Title: the title

    <Stack.Navigator>
          <Stack.Screen
            name="Home"
            component={HomeScreen}
            options={{ title:}} />
        </Stack.Navigator>
    Copy the code
  • Use the title passed by the parameter

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

    Navigation – The navigation of the page

    Route – The route of the page;

    <Stack.Navigator>
        <Stack.Screen
          name="Home"
          component={ProfileScreen}
          options={({ route}) = > ({ title: route.params.name })}
         />
    </Stack.Navigator>
    Copy the code
  • SetOptions () sets the properties on the Tabbar component

    navigation.setOptions({ title: 'Updated! ' })
    Copy the code
  • Header header

    • HeaderStyle sets the header headerStyle

      headerStyle: {
        	backgroundColor: 'red',},Copy the code
    • HeaderTinColor: Sets the header title bar font color

    • HeaderTitleStyle: Sets the header header style

      headerTitleStyle: {
        	fontWeight: 'bold'.fontSize: 30,},Copy the code
  • Custom header header bar

    • headerTitleCustom header text that can be passed to a component
    • headerBackTitleVisibleWhether to display the text for the return button
    • headerBackTitleSets the text for the return button
    • headerRightSets the style to the right of the header header to pass a component
    • headerBackImageCustom return icon that returns a picture component

Nesting a navigator means rendering a navigator on the screen of another navigator; In general, the home page will have a Tabbar bar, as follows:

import React, { Component } from 'react';

import { NavigationContainer } from '@react-navigation/native';
import {
    createStackNavigator,
    HeaderBackButton,
    StackNavigationProp,
} from '@react-navigation/stack';
import Found from '.. /pages/found/Found';
import List from '.. /pages/list/List';
import Me from '.. /pages/me/Me';
import BottomTabs from './ButtomTab';
import Detail from '.. /pages/detail/Detail';
import Login from '.. /pages/login/Login';
import Search from '.. /pages/search/Search';
import Play from '.. /pages/play/Play';
import MVPlay from '.. /pages/mv-play/MVPlay';
import CustomTitleBar from '.. /pages/custom-title-bar/CustomTitleBar';
import CustomHeader from '.. /components/CustomHeader';
import { Button } from '@ant-design/react-native';
import { Alert, Image } from 'react-native';

export type RootStackParamList = {
    BottomTabs: undefined;
    List: undefined;
    Found: undefined;
    Me: undefined;
    Login: undefined;
    Detail: {
        topId: number;
    };
    Search: undefined;
    Play: {
        id: number;
    };
    MVPlay: {
        vid: string;
    };
    CustomTitleBar: undefined;
};

export type RootStackNavigation = StackNavigationProp<RootStackParamList>;

const Stack = createStackNavigator<RootStackParamList>();
export default class Navigator extends Component {
    render() {
        return (
            <NavigationContainer>
                <Stack.Navigator>
                    <Stack.Screen
                        name="BottomTabs"
                        component={BottomTabs}
                        options={{
                            headerTitle:'home',headerStyle: {
                                backgroundColor: 'red'},headerTintColor: '#fff',
                            headerTitleStyle: {
                                fontWeight: 'bold',
                                fontSize: 30,}}} / >
                    <Stack.Screen
                        name="List"
                        component={List}
                        options={{ headerTitle:}} />
                    <Stack.Screen
                        name="Found"
                        component={Found}
                        options={{ headerTitle:'discover'}} />
                    <Stack.Screen
                        name="Me"
                        component={Me}
                        options={{ headerTitle:'my'}} />
                    <Stack.Screen
                        name="Login"
                        component={Login}
                        options={{ headerTitle:'Login'}} />
                    <Stack.Screen
                        name="Detail"
                        component={Detail}
                        options={{ headerTitle:'Playlist'}} />
                    <Stack.Screen
                        name="Search"
                        component={Search}
                        options={{ headerTitle:'search'}} />
                    <Stack.Screen
                        name="Play"
                        component={Play}
                        options={{ headerTitle:'Song'}} />
                    <Stack.Screen
                        name="MVPlay"
                        component={MVPlay}
                        options={{ headerTitle: 'mv' }}
                    />
                    <Stack.Screen
                        name="CustomTitleBar"
                        component={CustomTitleBar}
                        options={{
                            headerTitle: (props) = > <CustomHeader {. props} / >,
                            // headerBackTitleVisible: false,
                            headerBackTitle: '1234',
                            headerRight: () => (
                                <Button onPress={()= > Alert.alert('right')}>
                                    right
                                </Button>
                            ),
                            headerBackImage: () => (
                                <Image
                                    source={{
                                        uri: 'https://qpic.y.qq.com/music_cover/DhpicvGxCZozibtVUC0Q03Oia0h9DnKUNHPdPL3oD2tqUJiaYJUv1jvlEXbPvCCy4Vql/300?n=1'}}style={[
                                        {
                                            width: 60.height: 60.marginRight: 20,},]} / >
                            ),
                        }}
                    />
                </Stack.Navigator>
            </NavigationContainer>); }}Copy the code

The complete code is as follows:

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import React, { Component } from 'react';
import {
    getFocusedRouteNameFromRoute,
    RouteProp,
    TabNavigationState,
} from '@react-navigation/native';
import { RootStackNavigation, RootStackParamList } from './index';
import Home from '.. /pages/home/Home';
import List from '.. /pages/list/List';
import Found from '.. /pages/found/Found';
import Me from '.. /pages/me/Me';

export type BottomTabParamList = {
    Home: undefined;
    List: undefined;
    Found: undefined;
    Me: undefined;
};

const Tab = createBottomTabNavigator<BottomTabParamList>();

type Route = RouteProp<RootStackParamList, 'BottomTabs'> & { state? : TabNavigationState<BottomTabParamList>; };interface IProps {
    navigation: RootStackNavigation;
    route: Route;
}

export default class BottomTabs extends Component<IProps> {
    // Get the title of each page
    getHeaderTitle(route: Route): string {
        const routeName = getFocusedRouteNameFromRoute(route) ?? 'Home';

        switch (routeName) {
            case 'Home':
                return 'home';
            case 'List':
                return 'list';
            case 'Found':
                return 'found';
            case 'Me':
                return 'I';
            default:
                return 'home'; }}componentDidUpdate() {
        const { navigation, route } = this.props;
        navigation.setOptions({
            headerTitle: this.getHeaderTitle(route),
        });
    }
  
    render() {
        return (
            <Tab.Navigator
                tabBarOptions={{
                    activeTintColor: '#f86442', / / modifytabbarActivate color}}>
                <Tab.Screen
                    name="Home"
                    component={Home}
                    options={{ tabBarLabel:}} />
                <Tab.Screen
                    name="List"
                    component={List}
                    options={{ tabBarLabel:}} />
                <Tab.Screen
                    name="Found"
                    component={Found}
                    options={{ tabBarLabel:'discover'}} />
                <Tab.Screen
                    name="Me"
                    component={Me}
                    options={{ tabBarLabel:'my'}} />
            </Tab.Navigator>); }}Copy the code

There is a bottom tabbar for the home page, lists, Find, and my pages. This is an embedded function. The component with the Tabbar is loaded for the first time. Click on the tabbar button to switch.

React Navigation life cycle

We used a stack navigator with two screens (Home and Detail) and learned how to navigate between routes with navigation.navigate(‘RouteName’).

In this case, an important question is: What happens to Home when we leave it, or when we return to it? How does the route find out if the user is leaving it or returning it?

If you’re going to do reactive navigation from a Web background, you can assume that when the user navigates from route A to route B, A will be unloaded (its componentWillUnmount is called) and A will be loaded again when the user returns to it. While these React lifecycle methods are still valid and used in React-Navigation, their usage is different from the Web. This is driven by the more complex requirements of mobile navigation.

For example, a stack navigator with screens A and B. After navigating to A, call its componentDidMount. When B is pushed, its componentDidMount is also called, but A is still mounted on the stack, so its componentWillUnmount is not called.

When returning from B to A, B’s componentWillUnmount is called, but A’s componentDidMount is not called, because A keeps mounting; Similar results can be combined with nested navigation. Consider a tag navigator with two tags, each of which is a stack navigator:

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

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

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

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

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')}
            />
        </View>
    );
}


const Tab = createBottomTabNavigator();
const SettingsStack = createStackNavigator();
const HomeStack = createStackNavigator();

export default function App() {
    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

We went from HomeScreen to DetailScreen and then used the TAB bar to switch to SetterScreen and navigate to profileScreen. After that, we mounted the 4 screen components. If you use the TAB bar to switch back to HomeStack, You’ll notice that the detailsScreen-Homestack navigation state is preserved!

React Navigation declares events in the cycle

Foucs listens for focusing events; The focus event of the HTML input tag does the same thing

Blur listens for events beyond focus. The blur event on the HTML input tag does the same thing

function Profile({ navigation }) {
    React.useEffect(() = > {
        const unsubscribe = navigation.addListener('focus'.() = > {
          // Screen was focused
          // Do something
        });

      	return unsubscribe;
    }, [navigation]);

    return <ProfileContent />;
}
Copy the code

The useFoucsEffect hook function can be used in function components to listen for execution events

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

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