首页 > 解决方案 > 在堆栈之间导航时出现 React Navigation 5 类型错误

问题描述

我在使用 react-navigation 5 时遇到了一些 TypeScript 错误。我确定这是我在输入内容/构建应用程序方面做错的事情,但我不确定是什么。

我以文档中的这些指南为起点:

https://reactnavigation.org/docs/en/tab-based-navigation.html#a-stack-navigator-for-each-tab https://reactnavigation.org/docs/en/typescript.html

我想要一个这样的应用程序结构:

运行时一切正常,但是当我尝试从一个堆栈中的页面导航到另一个堆栈中的页面时,例如从新闻详细信息页面导航到设置页面时,我遇到了某种类型的错误。

这是我目前拥有的代码。

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

import { RouteProp } from '@react-navigation/core';

enum AppRoute {
    // Home Stack
    HOME = 'HOME',
    NEWS_DETAILS = 'NEWS_DETAILS',

    // Settings Stack
    SETTINGS = 'SETTINGS',
}

type HomeStackParamList = {
    [AppRoute.HOME]: undefined;
    [AppRoute.NEWS_DETAILS]: {
        id: number;
    };
}

type SettingsStackParamList = {
    [AppRoute.SETTINGS]: undefined;
}


type HomeProps = {
    navigation: StackNavigationProp<
        HomeStackParamList,
        AppRoute.HOME
    >;
    route: RouteProp<HomeStackParamList, AppRoute.HOME>;
}

type NewsDetailsProps = {
    navigation: StackNavigationProp<
        HomeStackParamList,
        AppRoute.NEWS_DETAILS
    >;
    route: RouteProp<HomeStackParamList, AppRoute.NEWS_DETAILS>;
}

type SettingsProps = {
    navigation: StackNavigationProp<
        SettingsStackParamList,
        AppRoute.SETTINGS
    >;
    route: RouteProp<SettingsStackParamList, AppRoute.SETTINGS>;
}


// ----------------------------------------------------------------------------

function HomeScreen(props: HomeProps) {
    const { navigation } = props;

    return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
            <Text>Home screen</Text>
            <Button
                title="Go to Details"
                onPress={() => navigation.navigate(AppRoute.NEWS_DETAILS, { id: 1 })}
            />
            <Button
                title="Go to Settings"
                onPress={() => navigation.navigate(AppRoute.SETTINGS)}
            />
        </View>
    );
}


function DetailsScreen(props: NewsDetailsProps) {
    return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
            <Text>Details! {props.route.params.id}</Text>
        </View>
    );
}


function SettingsScreen(props: SettingsProps) {
    const { navigation } = props;

    return (
        <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
            <Text>Settings screen</Text>
            <Button
                title="Go to Home -> Details"
                onPress={() => navigation.navigate(AppRoute.NEWS_DETAILS, { id: 2 })}
            />
        </View>
    );
}

const HomeStack = createStackNavigator<HomeStackParamList>();

function HomeStackScreen() {
    return (
        <HomeStack.Navigator>
            <HomeStack.Screen name={AppRoute.HOME} component={HomeScreen} />
            <HomeStack.Screen name={AppRoute.NEWS_DETAILS} component={DetailsScreen} />
        </HomeStack.Navigator>
    );
}


const SettingsStack = createStackNavigator<SettingsStackParamList>();

function SettingsStackScreen() {
    return (
        <SettingsStack.Navigator>
            <SettingsStack.Screen name={AppRoute.SETTINGS} component={SettingsScreen} />
        </SettingsStack.Navigator>
    );
}


const Tab = createBottomTabNavigator();

type TabNavigatorProps = React.ComponentProps<typeof Tab.Navigator>;

export const AppNavigator = (props: Partial<TabNavigatorProps>): React.ReactElement => {
    return (
        <Tab.Navigator>
            <Tab.Screen name="Home" component={HomeStackScreen} />
            <Tab.Screen name="Settings" component={SettingsStackScreen} />
        </Tab.Navigator>
    );
}

这是我得到的错误:

No overload matches this call.
  Argument of type '[AppRoute.SETTINGS]' is not assignable to parameter of type '[AppRoute.HOME | AppRoute.NEWS_DETAILS] | [AppRoute.HOME | AppRoute.NEWS_DETAILS, { id: number; }]'.
    Type '[AppRoute.SETTINGS]' is not assignable to type '[AppRoute.HOME | AppRoute.NEWS_DETAILS]'.
      Type 'AppRoute.SETTINGS' is not assignable to type 'AppRoute.HOME | AppRoute.NEWS_DETAILS'.
  Overload 2 of 2, '(route: { key: string; params?: { id: number; }; } | { name: AppRoute.HOME | AppRoute.NEWS_DETAILS; key?: string; params: { id: number; }; }): void', gave the following error.
    Argument of type 'AppRoute.SETTINGS' is not assignable to parameter of type '{ key: string; params?: { id: number; }; } | { name: AppRoute.HOME | AppRoute.NEWS_DETAILS; key?: string; params: { id: number; }; }'.ts(2769)

我想我明白为什么会发生这种情况,这是因为 HomeStackParamList 没有在其中定义设置路由。我应该为每个堆栈页面参数创建一个联合类型并在任何地方使用它,这样我就没有这个错误,还是有更好的方法来构建它?

我想我可以像这样创建所有参数列表的联合类型,但我不确定这是否是正确的方法?像这样的东西:

type HomeStackParamList = {
    [AppRoute.HOME]: undefined;
    [AppRoute.HOME_DETAILS]: {
        id: number;
    };
}

type SettingsStackParamList = {
    [AppRoute.SETTINGS]: undefined;
}

type AppStackParamList = HomeStackParamList & SettingsStackParamList;

type HomeProps = {
    navigation: StackNavigationProp<
        AppStackParamList,
        AppRoute.HOME
    >;
    route: RouteProp<AppStackParamList, AppRoute.HOME>;
}

type DetailsProps = {
    navigation: StackNavigationProp<
        AppStackParamList,
        AppRoute.HOME_DETAILS
    >;
    route: RouteProp<AppStackParamList, AppRoute.HOME_DETAILS>;
}

type SettingsProps = {
    navigation: StackNavigationProp<
        AppStackParamList,
        AppRoute.SETTINGS
    >;
    route: RouteProp<AppStackParamList, AppRoute.SETTINGS>;
}

任何帮助我指出正确方向的建议将不胜感激,谢谢

标签: typescriptreact-nativereact-navigation

解决方案


是的,参数列表的联合对于这个用例来说很好。


推荐阅读