1

Command installation

// 安装基础包 ^6.0.6
yarn add @react-navigation/native -S
// 安装路由包 ^6.2.5
yarn add @react-navigation/native-stack -S

//RN版本0.65.1 React版本17.0.2
"react": "17.0.2",
"react-native": "0.65.1",

Routing configuration

Package reference

import { NavigationContainer, useNavigation } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator<RootStackParamList>();
const Navigator = Stack.Navigator;
const Screen = Stack.Screen;

Route list

// 路由页面配置
<NavigationContainer>
    <Stack.Navigator
        initialRouteName={Views.Home}
        screenOptions={{
            headerShadowVisible: false, // android 导航去阴影
            headerTitleAlign: 'center', // 标题居中
            // 设置导航栏字体样式
            headerTitleStyle: {
                fontSize: 17,
                color: '#333333',
                fontFamily: 'PingFangSC-Semibold',
                fontWeight: '700',
            },
            headerLeft: () => headerLeft(),
        }}
    >
        <Stack.Screen
            name={Views.Home}
            component={Home}
            options={{ title: '每日任务' }}
        />
        <Stack.Screen
            name={Views.NewTask}
            component={NewTask}
            options={{ title: '新手任务' }}
        />
        <Stack.Screen
            name={Views.Redeem}
            component={Redeem}
            options={{ title: '积分兑换' }}
        />
        <Stack.Screen
            name={Views.Rule}
            component={Rule}
            options={{ title: '积分兑换规则' }}
        />
    </Stack.Navigator>
</NavigationContainer>

Detailed attribute parameters

Stack.Navigator

Navigation global configuration, the parameters configured again are all effective on the navigation of all routing pages, the specific properties are as follows

initialRouteName: //指定路由首页 类比React的跟路由页面
// 用于导航器中屏幕的默认选项
screenOptions: {
    headerShadowVisible: false, // android 导航去阴影 默认true开启状态
    headerTitleAlign: 'center', // 标题居中 默认 'left'
    headerTitle: '标题', //全局标题 在此设置是不生效的 默认展示路由页面的name
    // 设置导航栏字体样式
    headerTitleStyle: {
        fontSize: 17,
        color: '#333333',
        fontFamily: 'PingFangSC-Semibold',
        fontWeight: '700',
    },
    headerTintColor: 'red', // 导航栏字体颜色设置 如果设置了headerTitleStyle则此处设置不生效
    statusBarStyle: 'light' //"inverted" | "auto" | "light" | "dark" | undefined 状态栏配置
    headerLeft: React.ReactNode, //导航左侧区域按钮配置 不配置默认展示左箭头返回图标
    headerRight: React.ReactNode //导航右侧区域配置 默认无
}

The above basic configuration can basically meet the daily development of most businesses

Stack.Screen

Page navigation configuration, the configuration here will override the global configuration, the specific attribute parameters are as follows:

const Home = lazy(() => import('./views/home'));
name= 'Home' //指定的路由页面的名称 必填属性
component= Home // 路由React页面挂载 必填属性
initialParams={{ itemId: 42 }} //页面初始化参数
// 路由页面导航配置 此处的配置会覆盖全局的screenOptions
options={{ 
  title: '积分兑换规则', //路由页面标题 
  headerLeft: React.ReactNode, //导航左侧区域按钮配置 不配置默认展示左箭头返回图标
  headerRight: React.ReactNode //导航右侧区域配置 默认无
}}

Routing usage

Since the new version of RN is basically developed by Hooks+TypeScript, many types of declarations are required when using it.

Declaration file

First, add a global declaration file to facilitate the calling of custom hooks (described in detail below);

My project development catalog is as follows:

image-20211218164107497

First, add a global ts declaration file index.ts under types. The content is as follows:

import { RouteProp } from '@react-navigation/native'; // 获取route的props
// 枚举出来所有的路由页面的Name
export enum Views {
    Home = 'Home',
    NewTask = 'NewTask',
    Redeem = 'Redeem',
    Rule = 'Rule',
}
interface NewTaskProps {
    title: string;
    action: string;
    funcName: string;
    params: any;
}
// 定义每个路由页面需要传达到下个页面的参数 在目的页面里面声明要接受的参数
export type RootStackParamList = {
    [Views.Home]: undefined;

    [Views.NewTask]:
        | {
              /** @description 声明往子组件里面的传参 */
              item: NewTaskProps;
              callback: () => void;
          }
        | undefined;
    [Views.Redeem]:
        | {
              /** @description 监听页面返回回调父页面 */ callback: () => void;
          }
        | undefined;
    [Views.Rule]: undefined;
};
// 定义声明每个子路由界面接收的具体数据类型useRoute 后面详解使用
export type RootRouteType = RouteProp<RootStackParamList>;
// This registers which makes navigation fully type-safe.
// https://reactnavigation.org/docs/typescript#specifying-default-types-for-usenavigation-link-ref-etc
// 全局声明useNavigation自定义hooks方法的参数
declare global {
    namespace ReactNavigation {
        interface RootParamList extends RootStackParamList {}
    }
}

Custom hooks

Currently react-navigation provides custom hooks methods useNavigation, useRoute, etc., focusing on the use of routing

useNavigation

1. Return to monitor navigation.goBack()

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

// 左侧返回按钮
const headerLeft = () => {
    // hooks里面获取导航器对象
    const navigation = useNavigation();
    return (
        <TouchableOpacity
            onPress={() => {
                // 如果无法在使用路由退出后 调用native协议关闭当前RN容器
                navigation.canGoBack() ? navigation.goBack() : Alert.alert('路由首页');
            }}
        >
            <Image
                style={{
                    height: 25,
                    width: 25,
                }}
                source={require('./images/back.png')}
            />
        </TouchableOpacity>
    );
};

2. Route jump navigation.navigate

import React, { FC } from 'react';
import { useNavigation } from '@react-navigation/native';
import { Views } from '@types'; //此处配置了alias 可以直接使用@
const Home: FC = () => {
  // 自定义hooks里面调用导航对象
    const navigation = useNavigation();
  // 普通不带参数跳转
  const jumpNewTask = () => {
    //不带参数的普通跳转 如果没有全局的ReactNavigation声明 按文档调用会报如下错误一的问题
    navigation.navigate(Views.NewTask); 
  }
  // 带参数跳转
  const jumpNewTask = () => {
    //如果不再目的页面做入参的声明会有如下报错(错误二)
    navigation.navigate(Views.NewTask, {
            item: {
                title: '弹窗',
                action: 'CSTShowDialog',
                funcName: 'dialog',
                params: {
                    title: '温馨提示',
                    content: '请上传证件照,否则发帖需要扣费10元',
                    btns: [
                        { color: '#ff552e', text: '确定' },
                        { color: '#000000', text: '取消' },
                    ],
                },
            },
            callback: () => {
                // 新手任务返回首页 拉取积分信息
                getTaskInfo();
            },
        }); 
  }
}

Error one

image-20211218171256398

Error two

image-20211218171833049

3. Rewrite navigation.setOptions

import React, { FC, useLayoutEffect, useEffect } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { useNavigation, useRoute } from '@react-navigation/native'
const Redeem: FC = () => {
  const navigation = useNavigation();
    const headerRight = () => {
        return (
            <TouchableOpacity
                onPress={() => {
                    navigation.navigate(Views.Rule);
                }}
            >
                <Text style={styles.headerRight}>兑换规则</Text>
            </TouchableOpacity>
        );
    };
    useLayoutEffect(() => {
        navigation.setOptions({
            headerRight: () => headerRight(),
        });
    }, []);
}

4. Assign parameter navigation.setParams in the routing page

import React, { FC, useLayoutEffect } from 'react';
import { View, Text } from 'react-native';
import { useNavigation } from '@react-navigation/native';
const NewTask: FC = () => {
  const navigation = useNavigation();
  useLayoutEffect(() => {
        // 初始化赋值
        navigation.setParams({ testParam: 'test' });
    }, []);
}
export default NewTask;
// 页面内赋值一般要使用?:可选参数的方式声明 否则上个页面的路由跳转会报如下错误
//错误声明
[Views.NewTask]:
        | {
              /** @description 声明往子组件里面的传参 */
              item: NewTaskProps;
              testParam: string;
              callback: () => void;
          }
        | undefined;
// 正确的声明方式
[Views.NewTask]:
        | {
              /** @description 声明往子组件里面的传参 */
              item: NewTaskProps;
              testParam?: string;
              callback: () => void;
          }
        | undefined;

image-20211218173212258

5. Other

Other APIs will not be explained in detail temporarily

image-20211218173539012

useRoute

Route page parameters receive custom hooks

1. The routing parameters receive route.params

import React, { FC, useLayoutEffect } from 'react';
import { View, Text } from 'react-native';
import { useNavigation, useRoute } from '@react-navigation/native';
import { RootRouteType } from '@types';
const NewTask: FC = () => {
  const navigation = useNavigation();
  // @react-navigation/native自定义hooks里面获取路由参数对象
  // 错误 未声明直接使用报错如下 图一
  // const route = useRoute();
  // 正确使用方式 先声明后使用RootRouteType如上types里面的声明
  const route = useRoute<RootRouteType>();
  useLayoutEffect(() => {
        // 初始化赋值
        navigation.setParams({ testParam: 'test' });
        // 路由返回时触发调用父页面传入的callback方法,模拟路由回调
            return () => {
            route.params?.callback();
        };
    }, []);
  // 路由参数获取 
  const getParams = () => {
        // 页面获取到的路由参数如下:(图二所示)有父页面路由跳转的传参,有本页面类自己注册的路由页面参数testParam
        const params = route.params;
        console.log(params);
    };
}
export default NewTask;

Figure one

image-20211218175703512

Figure II

image-20211218174921946

2. Other

image-20211218181001395

Summarize

The above is a summary of the functions commonly used in my business development, and there is a deeper use, welcome to leave a message; the summary is not easy, please provide the original link for reprinting.


兰俊秋雨
5.1k 声望3.5k 粉丝

基于大前端端技术的一些探索反思总结及讨论