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

导航属性参考

您的应用程序中的每个screen组件都会自动提供navigation属性。该属性包含各种方便的函数,用于分派导航操作。它看起来像这样

  • navigation
    • navigate - 转到给定的屏幕,这将根据导航器以不同的方式运行
    • goBack - 返回到上一个屏幕,这将在堆栈中使用时弹出当前屏幕
    • reset - 用给定的状态替换导航器的导航状态
    • setParams - 将新的参数合并到路由的参数中
    • dispatch - 发送一个操作对象来更新导航状态
    • setOptions - 更新屏幕的选项
    • isFocused - 检查屏幕是否处于焦点状态
    • canGoBack - 检查是否可以从当前屏幕返回
    • getState - 获取导航器的导航状态
    • getParent - 获取父屏幕的导航对象(如果有)
    • addListener - 订阅屏幕的事件
    • removeListener - 取消订阅屏幕的事件

重要的是要强调navigation 属性不会传递给所有组件;只有screen 组件会自动接收此属性!React Navigation 在这里不做任何魔法。例如,如果你要定义一个MyBackButton 组件并将其作为屏幕组件的子组件渲染,你就无法访问它的navigation 属性。但是,如果你希望在任何组件中访问navigation 属性,可以使用 useNavigation 钩子。

setParams/setOptions 等应该只在useEffect/useLayoutEffect/componentDidMount/componentDidUpdate 等中调用。不要在渲染或构造函数中调用。

navigation 属性上存在一些基于当前导航器类型的附加函数。

如果导航器是堆栈导航器,则提供了一些navigategoBack 的替代方案,你可以使用任何你喜欢的方案。这些函数是

  • navigation
    • replace - 用新的屏幕替换当前屏幕
    • push - 将新屏幕推入堆栈
    • pop - 在堆栈中后退
    • popToTop - 返回堆栈顶部

有关这些方法的更多详细信息,请参阅 堆栈导航器助手原生堆栈导航器助手

如果导航器是标签导航器,则以下内容也可用

  • navigation
    • jumpTo - 转到标签导航器中的特定屏幕

有关这些方法的更多详细信息,请参阅 底部标签导航器助手Material 顶部标签导航器助手Material 底部标签导航器助手

如果导航器是抽屉导航器,则以下内容也可用

  • navigation
    • jumpTo - 转到抽屉导航器中的特定屏幕
    • openDrawer - 打开抽屉
    • closeDrawer - 关闭抽屉
    • toggleDrawer - 切换状态,即从关闭切换到打开,反之亦然

有关这些方法的更多详细信息,请参阅 抽屉导航器助手

通用 API 参考

您与 navigation 属性的大多数交互都将涉及 navigategoBacksetParams

navigate 方法允许我们导航到应用程序中的另一个屏幕。它接受以下参数

navigation.navigate(name, params)

  • name - 已在某处定义的路由的目标名称
  • params - 传递给目标路由的参数。
function HomeScreen({ navigation: { navigate } }) {
return (
<View>
<Text>This is the home screen of the app</Text>
<Button
onPress={() =>
navigate('Profile', { names: ['Brent', 'Satya', 'Michaś'] })
}
title="Go to Brent's profile"
/>
</View>
);
}

原生堆栈导航器 中,使用屏幕名称调用 navigate 会根据屏幕是否已存在而产生不同的行为。如果屏幕已存在于堆栈的历史记录中,它将返回到该屏幕并删除该屏幕之后的任何屏幕。如果屏幕不存在,它将推送一个新屏幕。

例如,如果您有一个历史记录为 Home > Profile > Settings 的堆栈,并且您调用 navigate(Profile),则结果屏幕将为 Home > Profile,因为它将返回到 Profile 并删除 Settings 屏幕。

默认情况下,屏幕由其名称标识。但您也可以使用 getId 属性来自定义它以考虑参数。

例如,假设您为 Profile 屏幕指定了 getId 属性

<Tab.Screen
name={Profile}
component={ProfileScreen}
getId={({ params }) => params.userId}
/>

现在,如果您有一个历史记录为 Home > Profile (userId: bob) > Settings 的堆栈,并且您调用 navigate(Profile, { userId: 'alice' }),则结果屏幕将为 Home > Profile (userId: bob) > Settings > Profile (userId: alice),因为它将添加一个新的 Profile 屏幕,因为没有找到匹配的屏幕。

goBack

goBack 方法允许我们返回到导航器中的前一个屏幕。

默认情况下,goBack 将从调用它的屏幕返回

function ProfileScreen({ navigation: { goBack } }) {
return (
<View>
<Button onPress={() => goBack()} title="Go back from ProfileScreen" />
</View>
);
}

从特定屏幕返回

考虑以下导航堆栈历史记录

navigation.navigate({ name: SCREEN, key: SCREEN_KEY_A });
navigation.navigate({ name: SCREEN, key: SCREEN_KEY_B });
navigation.navigate({ name: SCREEN, key: SCREEN_KEY_C });
navigation.navigate({ name: SCREEN, key: SCREEN_KEY_D });

现在您位于屏幕 D,并且想要返回到屏幕 A(弹出 D、C 和 B)。然后您可以使用navigate

navigation.navigate({ key: SCREEN_KEY_A }); // will go to screen A FROM screen D

或者,由于屏幕 A 是堆栈的顶部,您可以使用navigation.popToTop()

reset

reset方法允许我们用新状态替换导航器状态

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

reset中指定的 state 对象将用新的 state 对象替换现有的导航状态,即删除现有屏幕并添加新屏幕。如果您想在更改状态时保留现有屏幕,可以使用CommonActions.resetdispatch

警告

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

setParams

setParams方法允许我们更新当前屏幕的参数(route.params)。setParams的工作方式类似于 React 的setState - 它将提供的参数对象与当前参数进行浅合并。

function ProfileScreen({ navigation: { setParams } }) {
return (
<Button
onPress={() =>
setParams({
friends:
route.params.friends[0] === 'Brent'
? ['Wojciech', 'Szymon', 'Jakub']
: ['Brent', 'Satya', 'Michaś'],
title:
route.params.title === "Brent's Profile"
? "Lucy's Profile"
: "Brent's Profile",
})
}
title="Swap title and friends"
/>
);
}

setOptions

setOptions方法允许我们从组件内部设置屏幕选项。如果我们需要使用组件的 props、state 或 context 来配置我们的屏幕,这将很有用。

function ProfileScreen({ navigation, route }) {
const [value, onChangeText] = React.useState(route.params.title);

React.useEffect(() => {
navigation.setOptions({
title: value === '' ? 'No title' : value,
});
}, [navigation, value]);

return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<TextInput
style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
onChangeText={onChangeText}
value={value}
/>
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}

此处指定的任何选项都将与定义屏幕时指定的选项进行浅合并。

在使用navigation.setOptions时,我们建议在屏幕的options属性中指定一个占位符,并使用navigation.setOptions更新它。这可以确保更新选项的延迟对用户来说并不明显。它还可以与延迟加载的屏幕一起使用。

您也可以使用React.useLayoutEffect来减少更新选项的延迟。但我们建议您不要在支持 Web 和服务器端渲染的情况下这样做。

注意

navigation.setOptions旨在提供在必要时更新现有选项的能力。它不是屏幕上options属性的替代品。确保只在绝对必要时谨慎使用navigation.setOptions

屏幕可以使用addListener方法在navigation属性上添加监听器。例如,要监听focus事件

function Profile({ navigation }) {
React.useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
// do something
});

return unsubscribe;
}, [navigation]);

return <ProfileContent />;
}

有关可用事件和 API 用法的更多详细信息,请参阅导航事件

isFocused

此方法允许我们检查屏幕当前是否处于焦点状态。如果屏幕处于焦点状态,则返回true,否则返回false

const isFocused = navigation.isFocused();

此方法不会在值更改时重新渲染屏幕,主要在回调中使用。您可能希望使用useIsFocused而不是直接使用它,它将返回一个布尔值属性,指示屏幕是否处于焦点状态。

高级 API 参考

dispatch函数的使用频率要低得多,但如果您无法使用navigategoBack等可用方法来完成所需的操作,它是一个很好的备用方案。我们建议您尽量避免使用dispatch方法,除非绝对必要。

dispatch

dispatch方法允许我们发送一个导航操作对象,该对象决定如何更新导航状态。所有导航函数(如navigate)都在幕后使用dispatch

请注意,如果您想调度操作,您应该使用此库提供的操作创建器,而不是直接编写操作对象。

有关可用操作的完整列表,请参阅 导航操作文档

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

navigation.dispatch(
CommonActions.navigate({
name: 'Profile',
params: {},
})
);

在调度操作对象时,您还可以指定一些其他属性

  • source - 应被视为操作来源的路由键。例如,replace 操作将用给定键替换路由。默认情况下,它将使用调度操作的路由键。您可以显式传递 undefined 来覆盖此行为。
  • target - 应将操作应用于的 导航状态 的键。默认情况下,如果导航器未处理操作,则操作会冒泡到其他导航器。如果指定了 target,则如果具有相同键的导航器未处理操作,则操作不会冒泡。

示例

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

navigation.dispatch({
...CommonActions.navigate('Profile'),
source: 'someRoutekey',
target: 'someStatekey',
});

自定义操作创建器

也可以将操作创建器函数传递给 dispatch。该函数将接收当前状态,并需要返回一个要使用的导航操作对象

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

navigation.dispatch((state) => {
// Add the home route to the start of the stack
const routes = [{ name: 'Home' }, ...state.routes];

return CommonActions.reset({
...state,
routes,
index: routes.length - 1,
});
});

您可以使用此功能来构建您可以在应用程序中使用的自己的助手。以下是一个实现将屏幕插入最后一个屏幕之前的示例

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

const insertBeforeLast = (routeName, params) => (state) => {
const routes = [
...state.routes.slice(0, -1),
{ name: routeName, params },
state.routes[state.routes.length - 1],
];

return CommonActions.reset({
...state,
routes,
index: routes.length - 1,
});
};

然后像这样使用它

navigation.dispatch(insertBeforeLast('Home'));

canGoBack

此方法返回一个布尔值,指示当前导航器或任何父导航器中是否有任何导航历史记录可用。您可以使用它来检查是否可以调用 navigation.goBack()

if (navigation.canGoBack()) {
navigation.goBack();
}

不要使用此方法来渲染内容,因为这不会触发重新渲染。这仅用于回调、事件监听器等。

getParent

此方法返回当前导航器嵌套在其中的父导航器的导航道具。例如,如果您有一个堆栈导航器和一个嵌套在堆栈中的选项卡导航器,那么您可以在选项卡导航器的屏幕中使用 getParent 来获取从堆栈导航器传递的导航道具。

它接受一个可选的 ID 参数来引用特定的父导航器。例如,如果您的屏幕嵌套在多个嵌套级别中,位于带有 id 属性为 "LeftDrawer" 的抽屉导航器下,您可以直接引用它,而无需多次调用 getParent

要为导航器使用 ID,首先传递一个唯一的 id 属性

<Drawer.Navigator id="LeftDrawer">{/* .. */}</Drawer.Navigator>

然后在使用 getParent 时,而不是

// Avoid this
const drawerNavigation = navigation.getParent().getParent();

// ...

drawerNavigation?.openDrawer();

您可以这样做

// Do this
const drawerNavigation = navigation.getParent('LeftDrawer');

// ...

drawerNavigation?.openDrawer();

这种方法允许组件不必了解导航器的嵌套结构。因此,强烈建议在使用 getParent 时使用 id

如果不存在匹配的父导航器,此方法将返回 undefined。请确保在使用此方法时始终检查 undefined

getState

警告

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

此方法返回包含屏幕的导航器的状态对象。在极少数情况下,获取导航器状态可能很有用。您很可能不需要使用此方法。如果您确实需要,请确保您有充分的理由。

如果您需要状态来渲染内容,您应该使用 useNavigationState 而不是此方法。