结合静态和动态 API
虽然静态 API 有很多优点,但它不适合导航配置需要动态的用例。因此 React Navigation 支持静态和动态 API 之间的互操作。
¥While the static API has many advantages, it doesn't fit use cases where the navigation configuration needs to be dynamic. So React Navigation supports interop between the static and dynamic APIs.
请记住,静态 API 提供的功能(例如自动链接配置和自动 TypeScript 类型)需要整个配置都是静态的。如果部分配置是动态的,则需要手动处理这些部分。
¥Keep in mind that the features provided by the static API such as automatic linking configuration and automatic TypeScript types need the whole configuration to be static. If part of the configuration is dynamic, you'll need to handle those parts manually.
你可能希望通过 2 种方式结合静态和动态 API:
¥There are 2 ways you may want to combine the static and dynamic APIs:
静态根导航器,动态嵌套导航器
¥Static root navigator, dynamic nested navigator
如果你想保持配置静态,但需要对特定导航器使用动态配置,这将很有用。
¥This is useful if you want to keep your configuration static, but need to use a dynamic configuration for a specific navigator.
让我们考虑以下示例:
¥Let's consider the following example:
-
你有一个根堆栈导航器,其中包含屏幕中的选项卡导航器。
¥You have a root stack navigator that contains a tab navigator in a screen.
-
选项卡导航器使用动态 API 定义。
¥The tab navigator is defined using the dynamic API.
我们的静态配置如下所示:
¥Our static configuration would look like this:
import { createNativeStackNavigator } from '@react-navigation/native-stack';
const RootStack = createNativeStackNavigator({
screens: {
Home: {
screen: HomeScreen,
},
Feed: {
screen: FeedScreen,
linking: {
path: 'feed',
},
},
},
});
此处,FeedScreen
是一个渲染选项卡导航器的组件,使用动态 API 定义:
¥Here, FeedScreen
is a component that renders a tab navigator and is defined using the dynamic 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>
);
}
此代码可以工作,但我们缺少两件事:
¥This code will work, but we're missing 2 things:
-
顶部选项卡导航器中屏幕的链接配置。
¥Linking configuration for the screens in the top tab navigator.
-
顶部选项卡导航器中屏幕的 TypeScript 类型。
¥TypeScript types for the screens in the top tab navigator.
由于嵌套导航器是使用动态 API 定义的,因此我们需要手动处理它们。对于链接配置,我们可以在 Feed
屏幕的 linking
属性中定义屏幕:
¥Since the nested navigator is defined using the dynamic API, we need to handle these manually. For the linking configuration, we can define the screens in the linking
property of the Feed
screen:
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 的更多详细信息,请参阅 配置链接。
¥Here the screens
property is the same as how you'd define it with linking
config with the dynamic API. It can contain configuration for any nested navigators as well. See configuring links for more details on the API.
对于 TypeScript 类型,我们可以定义 FeedScreen
组件的类型:
¥For the TypeScript types, we can define the type of the FeedScreen
component:
import {
StaticScreenProps,
NavigatorScreenParams,
} from '@react-navigation/native';
type FeedParamList = {
Latest: undefined;
Popular: undefined;
};
type Props = StaticScreenProps<NavigatorScreenParams<FeedParamList>>;
function FeedScreen(_: Props) {
// ...
}
在上面的代码片段中:
¥In the above snippet:
-
我们首先在导航器中定义屏幕的参数列表类型,该列表定义每个屏幕的参数
¥We first define the param list type for screens in the navigator that defines params for each screen
-
然后我们使用
NavigatorScreenParams
类型来获取路由的params
类型,其中将包括嵌套屏幕的类型¥Then we use the
NavigatorScreenParams
type to get the type of route'sparams
which will include types for the nested screens -
最后,我们使用
params
和StaticScreenProps
的类型来定义屏幕组件的类型¥Finally, we use the type of
params
withStaticScreenProps
to define the type of the screen component
这是基于我们如何用动态 API 定义带有嵌套导航器的屏幕的类型。参见 嵌套导航器中的类型检查屏幕和参数。
¥This is based on how we'd define the type for a screen with a nested navigator with the dynamic API. See Type checking screens and params in nested navigator.
动态根导航器,静态嵌套导航器
¥Dynamic root navigator, static nested navigator
如果你已经有动态配置,但想要迁移到静态 API,这将很有用。这样,你可以一次迁移一个导航器。
¥This is useful if you already have a dynamic configuration, but want to migrate to the static API. This way you can migrate one navigator at a time.
让我们考虑以下示例:
¥Let's consider the following example:
-
你有一个根堆栈导航器,其中包含屏幕中的选项卡导航器。
¥You have a root stack navigator that contains a tab navigator in a screen.
-
根堆栈导航器是使用动态 API 定义的。
¥The root stack navigator is defined using the dynamic API.
我们的动态配置如下所示:
¥Our dynamic configuration would look like this:
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 定义:
¥Here, FeedScreen
is a component that renders a tab navigator and is defined using the static API:
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
const FeedTabs = createBottomTabNavigator({
screens: {
Latest: {
screen: LatestScreen,
},
Popular: {
screen: PopularScreen,
},
},
});
要将 FeedTabs
导航器用于 Feed
屏幕,我们需要使用 createComponentForStaticNavigation
函数:
¥To use the FeedTabs
navigator for the Feed
screen, we need to use the createComponentForStaticNavigation
function:
import { createComponentForStaticNavigation } from '@react-navigation/native';
const FeedScreen = createComponentForStaticNavigation(FeedTabs, 'Feed');
此外,我们可以为 FeedTabs
导航器生成 TypeScript 类型,并在 RootStack
的类型中使用它,而无需手动编写它们:
¥In addition, we can generate the TypeScript types for the FeedTabs
navigator and use it in the types of RootStack
without needing to write them manually:
import {
StaticParamList,
NavigatorScreenParams,
} from '@react-navigation/native';
type FeedTabsParamList = StaticParamList<typeof FeedTabs>;
type RootStackParamList = {
Home: undefined;
Feed: NavigatorScreenParams<FeedTabsParamList>;
};
类似地,我们可以为 FeedTabs
导航器生成链接配置,并在传递给 NavigationContainer
的链接配置中使用它:
¥Similarly, we can generate the linking configuration for the FeedTabs
navigator and use it in the linking configuration passed to 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
屏幕的链接配置。
¥This will generate the linking configuration for the Feed
screen based on the configuration of the FeedTabs
navigator.