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

CommonActions 参考

导航 action 是一个对象,至少包含一个 type 属性。在内部,action 可以被 路由器getStateForAction 方法处理,以从现有的 导航状态 返回一个新的状态。

每个导航 action 可以包含至少以下属性

  • type (必填) - 一个字符串,表示 action 的名称。
  • payload (可选) - 一个对象,包含关于 action 的额外信息。例如,它将包含 nameparams 用于 navigate
  • source (可选) - 应该被视为 action 来源的路由的 key。这用于某些 action 来确定要将 action 应用于哪个路由。默认情况下,navigation.dispatch 添加分发 action 的路由的 key。
  • target (可选) - 应该在其上应用 action 的 导航状态 的 key。

重要的是要强调,当 action 未被处理时,分发导航 action 不会抛出任何错误(类似于当您分发一个 action,该 action 未被 redux 中的 reducer 处理,并且没有任何反应)。

常用 actions

该库在 CommonActions 命名空间下导出多个 action 创建器。您应该使用这些 action 创建器,而不是手动编写 action 对象。

navigate action 允许导航到特定路由。它接受以下参数

  • name - 字符串 - 当前或父导航器中屏幕的目标名称。
  • params - 对象 - 用于目标路由的参数。
  • merge - 布尔值 - 参数是否应与现有路由参数合并,或替换它们(当导航到现有屏幕时)。默认为 false
navigation.dispatch(
CommonActions.navigate('Profile', { user: 'jane' })
);
Snack 上尝试

在堆栈导航器(堆栈原生堆栈)中,使用屏幕名称调用 navigate 将具有以下行为

  • 如果您已在具有相同名称的屏幕上,它将更新其参数,而不会推送新屏幕。
  • 如果您在不同的屏幕上,它会将新屏幕推送到堆栈上。
  • 如果指定了 getId prop,并且堆栈中的另一个屏幕具有相同的 ID,它将导航到该屏幕并更新其参数。
高级用法

navigate action 也可以接受一个对象作为参数,其中包含以下属性

  • name - 字符串 - 当前或父导航器中屏幕的目标名称
  • params - 对象 - 用于目标路由的参数。
  • merge - 布尔值 - 参数是否应与现有路由参数合并,或替换它们(当导航到现有屏幕时)。默认为 false
  • path - 字符串 - 与屏幕关联的路径(来自深度链接或通用链接)。

这主要在内部用于将路径与来自 URL 的屏幕关联。

reset

reset action 允许将 导航状态 重置为给定状态。它接受以下参数

navigation.dispatch(
CommonActions.reset({
index: 1,
routes: [
{
name: 'Profile',
params: { user: 'jane', key: route.params.key },
},
{ name: 'Home' },
],
})
);
Snack 上尝试

reset 中指定的状态对象将现有 导航状态 替换为新状态。这意味着,如果您提供没有 key 的新路由对象,或者具有不同 key 的路由对象,它将删除这些路由的现有屏幕并添加新屏幕。

如果您想保留现有屏幕,但只想修改状态,您可以将一个函数传递给 dispatch,您可以在其中获取现有状态。然后您可以根据需要更改它(确保不要改变现有状态,而是为您的更改创建新的状态对象),并返回具有所需状态的 reset action

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

navigation.dispatch((state) => {
// Remove all the screens after `Profile`
const index = state.routes.findIndex((r) => r.name === 'Profile');
const routes = state.routes.slice(0, index + 1);

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

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

使用 reset 重写历史记录

由于 reset action 可以使用新的状态对象更新导航状态,因此它可以用于重写导航历史记录。但是,在大多数情况下,不建议重写历史记录以更改返回堆栈

  • 它可能导致令人困惑的用户体验,因为用户期望能够返回到他们之前所在的屏幕。
  • 当支持 Web 平台时,浏览器的历史记录仍将反映旧的导航状态,因此如果用户使用浏览器的后退按钮,他们将看到旧屏幕 - 导致 2 种不同的体验,具体取决于用户按下哪个后退按钮。

因此,如果您有这样的用例,请考虑其他方法 - 例如,一旦用户导航回已更改的屏幕,就更新历史记录。

goBack

goBack action 创建器允许返回到历史记录中的上一个路由。它不接受任何参数。

navigation.dispatch(CommonActions.goBack());
Snack 上尝试

如果您想从特定路由返回,您可以添加一个 source 属性,引用路由 key,以及一个 target 属性,引用包含该路由的导航器的 key

navigation.dispatch({
...CommonActions.goBack(),
source: route.key,
target: route?.params?.key,
});
Snack 上尝试

默认情况下,分发 action 的路由的 key 作为 source 属性传递,target 属性为 undefined

preload

preload action 允许在导航到屏幕之前在后台预加载屏幕。它接受以下参数

  • name - 字符串 - 当前或父导航器中屏幕的目标名称。
  • params - 对象 - 用于目标路由的参数。
navigation.dispatch(
CommonActions.preload('Profile', { user: 'jane' })
);
Snack 上尝试

预加载屏幕意味着屏幕将在后台渲染。屏幕中的所有组件都将被挂载,并且 useEffect hooks 将被调用。当您想通过隐藏挂载重组件或加载数据的延迟来提高感知性能时,这可能很有用。

根据导航器的不同,preload 的工作方式可能有所不同

  • 在堆栈导航器(堆栈原生堆栈)中,屏幕将在屏幕外渲染,并在您导航到它时动画进入。如果指定了 getId,它将用于导航以识别预加载的屏幕。
  • 在标签或抽屉导航器(底部标签Material Top Tabs抽屉 等)中,现有屏幕将像 lazy 设置为 false 一样渲染。在已渲染的屏幕上调用 preload 将不会有任何效果。

当屏幕在堆栈导航器中预加载时,它将有一些限制

  • 它无法分发导航 actions(例如 navigate, goBack 等)。
  • 它无法使用 navigation.setOptions 更新选项。
  • 它无法监听来自导航器的事件(例如 focus, tabPress 等)。

一旦您导航到屏幕,navigation 对象将被更新。因此,如果您在 useEffect hook 中有一个事件监听器,并且依赖于 navigation,它将在屏幕导航到时添加任何监听器

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

return () => {
unsubscribe();
};
}, [navigation]);

同样,对于分发 actions 或更新选项,您可以检查屏幕是否获得焦点后再执行此操作

if (navigation.isFocused()) {
navigation.setOptions({ title: 'Updated title' });
}

setParams

setParams action 允许更新特定路由的参数。它接受以下参数

  • params - 对象 - 必填 - 要合并到现有路由参数中的新参数。
navigation.dispatch({
...CommonActions.setParams({ user: 'Wojtek' }),
Snack 上尝试

如果您想为特定路由设置参数,您可以添加一个 source 属性,引用路由 key

navigation.dispatch({
...CommonActions.setParams({ user: 'Wojtek' }),
source: route.key,
});
Snack 上尝试

如果 source 属性显式设置为 undefined,它将为获得焦点的路由设置参数。