跳至主要内容
版本:6.x

导航容器

NavigationContainer 负责管理您的应用程序状态,并将您的顶级导航器链接到应用程序环境。

容器负责平台特定的集成,并提供各种有用的功能

  1. linking 属性的深度链接集成。
  2. 屏幕跟踪状态持久化 等通知状态更改。
  3. 通过使用 React Native 的 BackHandler API 处理 Android 上的系统后退按钮。

用法

import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

const Stack = createNativeStackNavigator();

export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>{/* ... */}</Stack.Navigator>
</NavigationContainer>
);
}

引用

也可以将 ref 附加到容器,以访问各种辅助方法,例如,调度导航操作。这应该在您无法访问 navigation 属性的罕见情况下使用,例如 Redux 中间件。

示例

import {
NavigationContainer,
useNavigationContainerRef,
} from '@react-navigation/native';

function App() {
const navigationRef = useNavigationContainerRef(); // You can also use a regular ref with `React.useRef()`

return (
<View style={{ flex: 1 }}>
<Button onPress={() => navigationRef.navigate('Home')}>Go home</Button>
<NavigationContainer ref={navigationRef}>{/* ... */}</NavigationContainer>
</View>
);
}

如果您使用的是常规的 ref 对象,请记住,在某些情况下 ref 可能最初为 null(例如,当启用链接时)。为了确保 ref 已初始化,您可以使用 onReady 回调来在导航容器完成挂载时收到通知。

有关更多详细信息,请参阅 无需导航道具导航 指南。

ref 上的方法

ref 对象包含所有常见的导航方法,例如 navigategoBack 等。有关更多详细信息,请参阅 CommonActions 文档

示例

navigationRef.navigate(name, params);

所有这些方法的行为都将与在当前聚焦的屏幕内调用它们时相同。重要的是要注意,必须渲染一个导航器来处理这些操作。

除了这些方法之外,ref 对象还包含以下特殊方法

isReady

isReady 方法返回一个 boolean 值,指示导航树是否已准备就绪。当 NavigationContainer 包含至少一个导航器并且所有导航器都已完成挂载时,导航树就已准备就绪。

这可用于确定是否可以安全地调度导航操作而不会出现错误。有关更多详细信息,请参阅 处理初始化

resetRoot

resetRoot 方法允许您将导航树的状态重置为指定的状态对象

navigationRef.resetRoot({
index: 0,
routes: [{ name: 'Profile' }],
});

reset 方法不同,此方法作用于根导航器,而不是当前聚焦屏幕的导航器。

getRootState

getRootState 方法返回一个 导航状态 对象,其中包含导航树中所有导航器的导航状态

const state = navigationRef.getRootState();

请注意,如果当前没有渲染任何导航器,则返回的 state 对象将为 undefined

getCurrentRoute

getCurrentRoute 方法返回整个导航树中当前聚焦屏幕的路由对象

const route = navigationRef.getCurrentRoute();

请注意,如果当前没有渲染任何导航器,则返回的 route 对象将为 undefined

getCurrentOptions

getCurrentOptions 方法返回整个导航树中当前聚焦屏幕的选项。

const options = navigationRef.getCurrentOptions();

请注意,如果当前没有渲染任何导航器,则返回的 options 对象将为 undefined

addListener

addListener 方法允许您监听以下事件

state

每当导航树中任何导航器的 导航状态 发生变化时,都会触发此事件。

const unsubscribe = navigationRef.addListener('state', (e) => {
// You can get the raw navigation state (partial state object of the root navigator)
console.log(e.data.state);

// Or get the full state object with `getRootState()`
console.log(navigationRef.getRootState());
});

这类似于 onStateChange 方法。唯一的区别是 e.data.state 对象可能包含部分状态对象,而 onStateChange 中的 state 参数始终包含完整的状态对象。

options

每当导航树中当前聚焦屏幕的选项发生变化时,都会触发此事件。

const unsubscribe = navigationRef.addListener('options', (e) => {
// You can get the new options for the currently focused screen
console.log(e.data.options);
});

Props

initialState

此属性接受导航器的初始状态。这对于深层链接、状态持久化等情况很有用。

示例

<NavigationContainer initialState={initialState}>
{/* ... */}
</NavigationContainer>

提供自定义初始状态对象将覆盖通过链接配置或从浏览器 URL 获取的初始状态对象。如果您提供初始状态对象,请确保您没有在 web 上传递它,并且没有深层链接要处理。

示例

const initialUrl = await Linking.getInitialURL();

if (Platform.OS !== 'web' && initialUrl == null) {
// Only restore state if there's no deep link and we're not on web
}

有关如何持久化和恢复状态的更多详细信息,请参阅 状态持久化指南

onStateChange

警告

请将导航器的状态对象视为内部对象,并且可能会在次要版本中发生更改。避免使用 导航状态 状态对象中的属性,除非您确实需要它们。如果您无法在不依赖状态对象结构的情况下实现某些功能,请打开一个问题。

每当 导航状态 发生变化时都会调用的函数。它接收新的导航状态作为参数。

您可以使用它来跟踪聚焦屏幕、持久化导航状态等。

示例

<NavigationContainer
onStateChange={(state) => console.log('New state is', state)}
>
{/* ... */}
</NavigationContainer>

onReady

在导航容器及其所有子元素首次完成挂载后调用的函数。您可以使用它来

示例

<NavigationContainer
onReady={() => console.log('Navigation container is ready')}
>
{/* ... */}
</NavigationContainer>

onUnhandledAction

当导航操作未被任何导航器处理时调用的函数。

默认情况下,当操作未被处理时,React Navigation 会显示一条仅供开发人员查看的错误消息。您可以通过提供自定义函数来覆盖默认行为。

linking

用于深度链接、浏览器中的 URL 支持等的链接集成配置。

示例

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

function App() {
const linking = {
prefixes: ['https://mychat.com', 'mychat://'],
config: {
screens: {
Home: 'feed/:sort',
},
},
};

return (
<NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}>
{/* content */}
</NavigationContainer>
);
}

有关如何配置深度链接和 URL 集成的更多详细信息,请参阅配置链接指南

选项

linking.prefixes

要处理的 URL 前缀。您可以提供多个前缀来支持自定义方案以及通用链接

只有与这些前缀匹配的 URL 才会被处理。在解析之前,前缀将从 URL 中剥离。

示例

<NavigationContainer
linking={{
prefixes: ['https://mychat.com', 'mychat://'],
config: {
screens: {
Chat: 'feed/:sort',
},
},
}}
>
{/* content */}
</NavigationContainer>

这仅在 iOS 和 Android 上受支持。

linking.config

配置以微调如何解析路径。配置对象应代表应用程序中导航器的结构。

例如,如果我们在Home屏幕内有Catalog屏幕,并且希望它处理item/:id模式

{
screens: {
Home: {
screens: {
Catalog: {
path: 'item/:id',
parse: {
id: Number,
},
},
},
},
}
}

解析选项可以是对象或字符串

{
screens: {
Catalog: 'item/:id',
}
}

当指定字符串时,它等同于提供path选项。

path 选项是一个用于匹配路径的模式。任何以 : 开头的段都被识别为具有相同名称的参数。例如,item/42 将被解析为 { name: 'item', params: { id: '42' } }

initialRouteName 选项确保传递到该选项的路由名称将存在于导航器的状态中,例如,对于配置

{
screens: {
Home: {
initialRouteName: 'Feed',
screens: {
Catalog: {
path: 'item/:id',
parse: {
id: Number,
},
},
Feed: 'feed',
},
},
}
}

以及 URL:/item/42,状态将如下所示

{
routes: [
{
name: 'Home',
state: {
index: 1,
routes: [
{
name: 'Feed'
},
{
name: 'Catalog',
params: { id: 42 },
},
],
},
},
],
}

parse 选项控制如何解析参数。在这里,您可以提供要解析的参数的名称作为键,以及一个函数,该函数接受参数的字符串值并返回解析后的值

{
screens: {
Catalog: {
path: 'item/:id',
parse: {
id: id => parseInt(id, 10),
},
},
}
}

如果没有为解析参数提供自定义函数,它将被解析为字符串。

linking.enabled

可选的布尔值,用于启用或禁用链接集成。如果指定了 linking 属性,则默认为 true

linking.getInitialURL

默认情况下,链接会与 React Native 的 Linking API 集成,并使用 Linking.getInitialURL() 来提供对深度链接的内置支持。但是,您可能还想处理来自其他来源的链接,例如 Branch,或使用 Firebase 等推送通知。

您可以提供一个自定义的 getInitialURL 函数,您可以在其中返回我们应该用作初始 URL 的链接。如果存在要处理的 URL,则 getInitialURL 函数应返回一个 string,否则返回 undefined

例如,您可以执行以下操作来处理深度链接和 Firebase 通知

import messaging from '@react-native-firebase/messaging';

<NavigationContainer
linking={{
prefixes: ['https://mychat.com', 'mychat://'],
config: {
screens: {
Chat: 'feed/:sort',
},
},
async getInitialURL() {
// Check if app was opened from a deep link
const url = await Linking.getInitialURL();

if (url != null) {
return url;
}

// Check if there is an initial firebase notification
const message = await messaging().getInitialNotification();

// Get the `url` property from the notification which corresponds to a screen
// This property needs to be set on the notification payload when sending it
return message?.data?.url;
},
}}
>
{/* content */}
</NavigationContainer>;

此选项在 Web 上不可用。

linking.subscribe

getInitialURL 类似,您可以提供一个自定义的 subscribe 函数来处理任何传入的链接,而不是默认的深度链接处理。subscribe 函数将接收一个监听器作为参数,您可以在每次有新的 URL 要处理时使用它来调用它。它应该返回一个清理函数,您可以在其中取消订阅您已设置的任何事件监听器。

例如,您可以执行以下操作来处理深度链接和 Firebase 通知

import messaging from '@react-native-firebase/messaging';

<NavigationContainer
linking={{
prefixes: ['https://mychat.com', 'mychat://'],
config: {
screens: {
Chat: 'feed/:sort',
},
},
subscribe(listener) {
const onReceiveURL = ({ url }: { url: string }) => listener(url);

// Listen to incoming links from deep linking
const subscription = Linking.addEventListener('url', onReceiveURL);

// Listen to firebase push notifications
const unsubscribeNotification = messaging().onNotificationOpenedApp(
(message) => {
const url = message.data?.url;

if (url) {
// Any custom logic to check whether the URL needs to be handled
//...

// Call the listener to let React Navigation handle the URL
listener(url);
}
}
);

return () => {
// Clean up the event listeners
subscription.remove();
unsubscribeNotification();
};
},
}}
>
{/* content */}
</NavigationContainer>

此选项在 Web 上不可用。

linking.getStateFromPath

您可以选择通过提供自己的实现来覆盖 React Navigation 将链接解析为状态对象的方式。

示例

<NavigationContainer
linking={{
prefixes: ['https://mychat.com', 'mychat://'],
config: {
screens: {
Chat: 'feed/:sort',
},
},
getStateFromPath(path, config) {
// Return a state object here
// You can also reuse the default logic by importing `getStateFromPath` from `@react-navigation/native`
},
}}
>
{/* content */}
</NavigationContainer>
linking.getPathFromState

您可以选择覆盖 React Navigation 将状态对象序列化为链接的方式,方法是提供您自己的实现。如果您已指定 getStateFromPath,则需要这样做才能正确支持 Web。

示例

<NavigationContainer
linking={{
prefixes: ['https://mychat.com', 'mychat://'],
config: {
screens: {
Chat: 'feed/:sort',
},
},
getPathFromState(state, config) {
// Return a path string here
// You can also reuse the default logic by importing `getPathFromState` from `@react-navigation/native`
},
}}
>
{/* content */}
</NavigationContainer>

fallback

在解析深层链接时用作回退的 React 元素。默认值为 null

如果您有原生启动画面,请使用 onReady 而不是 fallback 属性。

documentTitle

默认情况下,React Navigation 会自动更新 Web 上的文档标题,以匹配聚焦屏幕的 title 选项。您可以使用此属性禁用或自定义它。它接受一个包含以下选项的配置对象

documentTitle.enabled

是否应启用文档标题处理。默认值为 true

documentTitle.formatter

如果您想自定义标题文本,可以使用自定义格式化程序。默认值为

(options, route) => options?.title ?? route?.name;

示例

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

function App() {
return (
<NavigationContainer
documentTitle={{
formatter: (options, route) =>
`${options?.title ?? route?.name} - My Cool App`,
}}
>
{/* content */}
</NavigationContainer>
);
}

theme

用于导航组件(如标题、标签栏等)的自定义主题。有关更多详细信息和使用指南,请参阅 主题指南

independent

警告

这是一个高级用例。除非您 100% 确定需要它,否则不要使用它。

此导航容器是否应独立于父容器。如果将其设置为 true,则此容器不能嵌套在另一个容器中。将其设置为 true 会断开任何子导航器与父容器的连接,并且不允许在它们之间导航。

在典型的 React Native 应用程序中,您可能不想将其设置为 true。这仅在您的导航树像自己的迷你应用程序一样工作,并且不需要导航到它们外部的屏幕时才有用。

如果您需要与第三方组件(如模态或底部工作表)集成,请避免使用它。请考虑使用 自定义导航器