跳到主要内容
版本:7.x

NavigationContainer

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

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

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

用法

当使用静态 API 时,由 createStaticNavigation 返回的组件等同于 NavigationContainer 组件。

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

const Stack = createNativeStackNavigator({
screens: {
/* ... */
},
});

const Navigation = createStaticNavigation(Stack);

export default function App() {
return <Navigation />;
}

Ref

可以传递 ref 到容器以访问各种辅助方法,例如,调度导航操作。这应该在极少数情况下使用,当你无法访问 navigation 对象 时,例如 Redux 中间件。

示例

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

export default 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>
<Navigation ref={navigationRef} />
</View>
);
}
Snack 上尝试

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

查看如何使用 TypeScript 设置 ref 此处

有关更多详细信息,请参阅 在没有导航 prop 的情况下导航 指南。

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

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

示例

<Navigation
initialState={initialState}
/>

有关状态对象结构的更多详细信息,请参阅 导航状态参考

提供自定义初始状态对象将覆盖通过链接配置或从浏览器 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

警告

将导航器的状态对象视为内部对象,并且在小版本更新中可能会发生更改。除非你真的需要,否则避免使用 导航状态 状态对象中的属性,除了 indexroutes。如果有一些功能你无法在不依赖状态对象结构的情况下实现,请提出 issue。

每次 导航状态 更改时都会调用的函数。它接收新的导航状态作为参数。

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

示例

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

onReady

在导航容器及其所有子项首次完成挂载后调用的函数。你可以将其用于

示例

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

如果容器内没有渲染导航器,则此回调不会触发。

可以使用 ref 上的 isReady 方法获取当前状态。

onUnhandledAction

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

默认情况下,当操作未被处理时,React Navigation 将显示仅在开发环境中显示错误消息。你可以通过提供自定义函数来覆盖默认行为。

示例

<Navigation
onUnhandledAction={(action) => console.error('Unhandled action', action)}
/>

linking

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

示例

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

const RootStack = createNativeStackNavigator({
screens: {
Home: {
screen: Home,
linking: {
path: 'feed/:sort',
},
},
},
});

const Navigation = createStaticNavigation(RootStack);

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

return (
<Navigation
linking={linking}
fallback={<Text>Loading...</Text>}
/>
);
}

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

选项

linking.prefixes

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

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

示例

<Navigation
linking={{
prefixes: ['https://mychat.com', 'mychat://'],
}}
fallback={<Text>Loading...</Text>}
/>

仅在 iOS 和 Android 上支持。

linking.config

用于微调如何解析路径的配置。

当使用动态 API 时,config 对象应表示应用程序中导航器的结构。

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

linking.enabled

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

当使用静态 API 时,可以传递 'auto' 以基于导航器的结构自动生成 config。有关更多详细信息,请参阅 配置链接指南

linking.getInitialURL

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

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

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

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

<Navigation
linking={{
prefixes: ['https://mychat.com', 'mychat://'],
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;
},
}}
/>;

此选项在 Web 上不可用。

linking.subscribe

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

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

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

<Navigation
linking={{
prefixes: ['https://mychat.com', 'mychat://'],
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();
};
},
}}
/>

此选项在 Web 上不可用。

linking.getStateFromPath

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

示例

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

你可以选择通过提供自己的实现来覆盖 React Navigation 将状态对象序列化为链接的方式。如果你已指定 getStateFromPath,则对于正确的 Web 支持,这是必要的。

示例

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

fallback

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

<Navigation
fallback={<Text>Loading...</Text>}
/>

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

documentTitle

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

documentTitle.enabled

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

documentTitle.formatter

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

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

示例

<Navigation
documentTitle={{
formatter: (options, route) =>
`${options?.title ?? route?.name} - My Cool App`,
}}
/>

theme

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

direction

应用程序中配置的文本方向。当 I18nManager.getConstants().isRTL 返回 true 时,默认为 'rtl',否则为 'ltr'

支持的值

  • 'ltr':从左到右的文本方向,适用于英语、法语等语言。
  • 'rtl':从右到左的文本方向,适用于阿拉伯语、希伯来语等语言。

示例

<Navigation
direction="rtl"
/>

这在各种导航器中用于根据文本方向调整内容,例如,在 RTL 语言中,抽屉导航器 中的抽屉位于右侧。

此属性告知 React Navigation 应用程序中的文本方向,它本身不会更改文本方向。如果你打算支持 RTL 语言,则务必将此属性设置为应用程序中配置的正确值。如果它与实际文本方向不匹配,则布局可能不正确。

在 Web 上,可能还需要在应用程序的根元素上设置 dir 属性,以确保文本方向正确

<html dir="rtl">
<!-- App content -->
</html>

direction 将通过 useLocale hook 在你自己的组件中使用

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

function MyComponent() {
const { direction } = useLocale();

// Use the direction
}
警告

此属性出于向后兼容性原因而存在。不建议在新项目中使用它。它将在未来的版本中删除。

在 React Navigation 的先前版本中,可以在不指定父屏幕名称的情况下导航到嵌套导航器中的屏幕,即 navigation.navigate(ScreenName) 而不是 navigation.navigate(ParentScreenName, { screen: ScreenName })

但是,它有一些问题

  • 它仅在导航器已挂载时才有效 - 使导航与其他逻辑耦合。
  • 它不适用于 TypeScript 类型。

navigationInChildEnabled 属性允许你选择加入此行为,以便更轻松地迁移旧代码。默认情况下禁用它。

对于新代码,请参阅 导航到嵌套导航器中的屏幕

独立的导航容器

警告

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

在大多数应用程序中,将只有一个 NavigationContainer。嵌套多个 NavigationContainer 将抛出错误。但是,在极少数情况下,拥有多个独立的导航树可能很有用,例如,在一个较大的应用程序中包含一个小型应用程序。

你可以使用 NavigationIndependentTree 组件包装嵌套的 NavigationContainer,使其独立于父导航树

import {
createStaticNavigation,
NavigationIndependentTree,
} from '@react-navigation/native';

/* content */

const Navigation = createStaticNavigation(RootStack);

function NestedApp() {
return (
<NavigationIndependentTree>
<Navigation />
</NavigationIndependentTree>
);
}

这样做会断开任何子导航器与父容器的连接,并且不允许它们之间进行导航。

如果你需要与第三方组件(如模态框或底部 sheet)集成,请避免使用此方法。考虑使用 自定义导航器