结合静态和动态 API
虽然静态 API 有许多优点,但它不适用于导航配置需要是动态的用例。因此,React Navigation 支持静态和动态 API 之间的互操作。
请记住,静态 API 提供的功能(例如自动链接配置和自动 TypeScript 类型)需要整个配置是静态的。如果部分配置是动态的,则需要手动处理这些部分。
您可能希望结合静态和动态 API 的方式有两种
静态根导航器,动态嵌套导航器
如果您想保持配置静态,但需要为特定导航器使用动态配置,这将非常有用。
让我们考虑以下示例
- 您有一个根堆栈导航器,其中包含屏幕中的标签导航器。
- 标签导航器是使用动态 API 定义的。
我们的静态配置如下所示
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const RootStack = createNativeStackNavigator({
screens: {
Home: {
screen: HomeScreen,
},
Feed: {
screen: FeedScreen,
linking: {
path: 'feed',
},
},
},
});
在这里,FeedScreen
是一个组件,它渲染一个标签导航器,并使用动态 API 定义
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();
function FeedScreen() {
return (
<Tab.Navigator>
<Tab.Screen name="Latest" component={LatestScreen} />
<Tab.Screen name="Popular" component={PopularScreen} />
</Tab.Navigator>
);
}
此代码可以工作,但我们缺少 2 件事
- 顶部标签导航器中屏幕的链接配置。
- 顶部标签导航器中屏幕的 TypeScript 类型。
由于嵌套导航器是使用动态 API 定义的,因此我们需要手动处理这些。对于链接配置,我们可以在 Feed
屏幕的 linking
属性中定义屏幕
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const RootStack = createNativeStackNavigator({
screens: {
Home: {
screen: HomeScreen,
},
Feed: {
screen: FeedScreen,
linking: {
path: 'feed',
screens: {
Latest: 'latest',
Popular: 'popular',
},
},
},
},
});
这里的 screens
属性与您使用动态 API 定义 linking
配置的方式相同。它可以包含任何嵌套导航器的配置。有关 API 的更多详细信息,请参阅配置链接。
对于 TypeScript 类型,我们可以定义 FeedScreen
组件的类型
import {
StaticScreenProps,
NavigatorScreenParams,
} from '@react-navigation/native';
type FeedParamList = {
Latest: undefined;
Popular: undefined;
};
type Props = StaticScreenProps<NavigatorScreenParams<FeedParamList>>;
function FeedScreen(_: Props) {
// ...
}
在上面的代码片段中
- 我们首先为导航器中的屏幕定义参数列表类型,该类型为每个屏幕定义参数
- 然后,我们使用
NavigatorScreenParams
类型来获取路由params
的类型,这将包括嵌套屏幕的类型 - 最后,我们将
params
的类型与StaticScreenProps
一起使用,以定义屏幕组件的类型
这是基于我们如何使用动态 API 为带有嵌套导航器的屏幕定义类型。请参阅类型检查嵌套导航器中的屏幕和参数。
动态根导航器,静态嵌套导航器
如果您已经有动态配置,但想迁移到静态 API,这将非常有用。这样,您可以一次迁移一个导航器。
让我们考虑以下示例
- 您有一个根堆栈导航器,其中包含屏幕中的标签导航器。
- 根堆栈导航器是使用动态 API 定义的。
我们的动态配置如下所示
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const RootStack = createNativeStackNavigator();
function RootStackScreen() {
return (
<RootStack.Navigator>
<RootStack.Screen name="Home" component={HomeScreen} />
<RootStack.Screen name="Feed" component={FeedScreen} />
</RootStack.Navigator>
);
}
在这里,FeedScreen
是一个组件,它渲染一个标签导航器,并使用静态 API 定义
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
const FeedTabs = createBottomTabNavigator({
screens: {
Latest: {
screen: LatestScreen,
},
Popular: {
screen: PopularScreen,
},
},
});
要将 FeedTabs
导航器用于 Feed
屏幕,我们需要使用 createComponentForStaticNavigation
函数
import { createComponentForStaticNavigation } from '@react-navigation/native';
const FeedScreen = createComponentForStaticNavigation(FeedTabs, 'Feed');
此外,我们可以为 FeedTabs
导航器生成 TypeScript 类型,并在 RootStack
的类型中使用它,而无需手动编写它们
import {
StaticParamList,
NavigatorScreenParams,
} from '@react-navigation/native';
type FeedTabsParamList = StaticParamList<typeof FeedTabs>;
type RootStackParamList = {
Home: undefined;
Feed: NavigatorScreenParams<FeedTabsParamList>;
};
同样,我们可以为 FeedTabs
导航器生成链接配置,并在传递给 NavigationContainer
的链接配置中使用它
import { createPathConfigForStaticNavigation } from '@react-navigation/native';
const feedScreens = createPathConfigForStaticNavigation(FeedTabs);
const linking = {
prefixes: ['https://mychat.com', 'mychat://'],
config: {
screens: {
Home: '',
Feed: {
path: 'feed',
screens: feedScreens,
},
},
},
};
这将根据 FeedTabs
导航器的配置为 Feed
屏幕生成链接配置。