React Navigation 的嵌套导航器的 CompositeScreenProps 出现类型错误

问题描述 投票:0回答:1

我正在尝试遵循 本指南使用 TypeScript 和 React Navigation 进行类型检查,但每当我尝试导航到另一个选项卡中的屏幕时,我都会收到此错误:

Argument of type '[AppRoutes.LIBRARY_TAB, { screen: AppRoutes; params: { title: string; }; }]' is not assignable to parameter of type '[screen: AppRoutes.LIBRARY_TAB] | [screen: AppRoutes.LIBRARY_TAB, params: LibraryStackParamList]'.
  Type '[AppRoutes.LIBRARY_TAB, { screen: AppRoutes; params: { title: string; }; }]' is not assignable to type '[screen: AppRoutes.LIBRARY_TAB, params: LibraryStackParamList]'.
    Type at position 1 in source is not compatible with type at position 1 in target.
      Object literal may only specify known properties, and 'screen' does not exist in type 'LibraryStackParamList'.ts(2345)

这是我的组件道具:

type ConversationScreenProps = CompositeScreenProps<
    StackScreenProps<HomeStackParamList, AppRoutes.CONVERSATION>,
    BottomTabScreenProps<MainTabsParamList, AppRoutes.HOME_TAB>
>;

我正在像这样导航到屏幕:

navigation.navigate(AppRoutes.LIBRARY_TAB, {
    screen: AppRoutes.MEDITATION_PLAYER, // This is where the error shows up
    params: {
        title: suggestedMeditation,
    },
});

我的堆栈/选项卡嵌套结构是这样的:

- MainStack (NativeStackNavigator)
  - MainTabs (BottomTabNavigator)
    - HomeStack (StackNavigator, if I change this one to a NativeStackNavigator then I get an error about some gesture handler)
      - ConversationScreen
      - ...
    - LibraryStack (StackNavigator)
      - LibraryHomeScreen
      - MeditationsScreen
      - MeditationPlayerScreen
      - ...
  - PaywallStack (NativeStackNavigator)
    - AuthScreen
    - PlansScreen
  - ...

以下是我的选项卡和堆栈的一些类型:

export type MainStackParamList = {
    [AppRoutes.MAIN_TABS]: undefined;
    [AppRoutes.AUTH]: {
        justLogIn?: boolean;
    };
    [AppRoutes.PAYWALL_STACK]: undefined;
};

export type MainTabsParamList = {
    [AppRoutes.HOME_TAB]: HomeStackParamList;
    [AppRoutes.LIBRARY_TAB]: LibraryStackParamList;
    ...
};

export type LibraryStackParamList = {
    [AppRoutes.LIBRARY_HOME]: undefined;
    [AppRoutes.MEDITATIONS]: undefined;
    [AppRoutes.MEDITATION_PLAYER]: {
        title: string;
    };
    ...
};

export type ConversationScreenParamList = {
    conversationId?: string;
    journalEntryText?: string;
    myMapSection?: string;
    myMapSectionResponse?: string;
    newConvoTopic?: string;
};

export type HomeStackParamList = {
    [AppRoutes.HOME_SCREEN]: undefined;
    [AppRoutes.CONVERSATION]: ConversationScreenParamList | undefined;
    ...
};

这是我的选项卡/堆栈的更详细视图,以防有帮助:

const PaywallStackNav = createNativeStackNavigator<PaywallStackParamList>();

const PaywallStack = () => (
    <PaywallStackNav.Navigator screenOptions={{ headerShown: false }}>
        <PaywallStackNav.Screen name={AppRoutes.AUTH} component={Auth} />
        <PaywallStackNav.Screen name={AppRoutes.PLANS} component={PlansScreen} />
    </PaywallStackNav.Navigator>
);

const MainStack = createNativeStackNavigator<MainStackParamList>();
const Main = () => (
    <MainStack.Navigator screenOptions={{ headerShown: false }}>
        <MainStack.Screen name={AppRoutes.MAIN_TABS} component={MainTabs} />
        <MainStack.Screen
            name={AppRoutes.PAYWALL_STACK}
            component={PaywallStack}
            options={{ presentation: "modal" }}
        />
    </MainStack.Navigator>
);

const Tabs = createBottomTabNavigator<MainTabsParamList>();
const LibraryStack = createStackNavigator<LibraryStackParamList>();
const HomeStack = createStackNavigator<HomeStackParamList>();

const LibraryTab = () => (
    <LibraryStack.Navigator initialRouteName={AppRoutes.LIBRARY_HOME}>
        <LibraryStack.Screen 
            name={AppRoutes.LIBRARY_HOME} 
            component={LibraryHomeScreen}
            options={{ title: "Library" }}
        />
        <LibraryStack.Screen 
            name={AppRoutes.MEDITATION_PLAYER} 
            component={MeditationPlayerScreen}
        />
    </LibraryStack.Navigator>
);

const HomeTab = () => (
    <HomeStack.Navigator initialRouteName={AppRoutes.HOME_SCREEN}>
        <HomeStack.Screen name={AppRoutes.HOME_SCREEN} component={Home} />
        <HomeStack.Screen name={AppRoutes.CONVERSATION} component={Conversation} />
    </HomeStack.Navigator>
);

const MainTabs = () => (
    <Tabs.Navigator initialRouteName={AppRoutes.HOME_TAB}>
        <Tabs.Screen
            name={AppRoutes.LIBRARY_TAB}
            component={LibraryTab}
            options={{
                tabBarLabel: "Library",
                tabBarIcon: ({ focused }) => <TabBarIcon focused={focused} icon="library-outline" />
            }}
        />
        <Tabs.Screen
            name={AppRoutes.HOME_TAB}
            component={HomeTab}
            options={{
                tabBarLabel: AppRoutes.HOME_SCREEN,
                tabBarIcon: ({ focused }) => <TabBarIcon focused={focused} icon="home-outline" />
            }}
        />
    </Tabs.Navigator>
);

我很确定我需要使用复合导航器(因为我正在跨选项卡/堆栈导航),但似乎我做错了?知道我需要更改什么才能不会引发类型错误吗?

让我知道我是否应该包含任何其他特定信息或代码(例如我在哪里声明我的堆栈/选项卡)。

reactjs react-native react-navigation react-navigation-stack react-navigation-bottom-tab
1个回答
0
投票

来自有关嵌套导航器类型检查的文档:

为了能够进行类型检查,我们需要从包含嵌套导航器的屏幕中提取参数。这可以使用 NavigatorScreenParams 实用程序来完成

所以你需要改变这个:

export type MainTabsParamList = {
    [AppRoutes.HOME_TAB]: HomeStackParamList;
    [AppRoutes.LIBRARY_TAB]: LibraryStackParamList;
    ...
};

对此:

export type MainTabsParamList = {
    [AppRoutes.HOME_TAB]: NavigatorScreenParams<HomeStackParamList>;
    [AppRoutes.LIBRARY_TAB]: <LibraryStackParamList>;
    ...
};
© www.soinside.com 2019 - 2024. All rights reserved.