CommonActions 参考
导航 action 是一个对象,至少包含一个 type
属性。在内部,action 可以被 路由器 的 getStateForAction
方法处理,以从现有的 导航状态 返回一个新的状态。
每个导航 action 可以包含至少以下属性
type
(必填) - 一个字符串,表示 action 的名称。payload
(可选) - 一个对象,包含关于 action 的额外信息。例如,它将包含name
和params
用于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
navigate
action 允许导航到特定路由。它接受以下参数
name
- 字符串 - 当前或父导航器中屏幕的目标名称。params
- 对象 - 用于目标路由的参数。merge
- 布尔值 - 参数是否应与现有路由参数合并,或替换它们(当导航到现有屏幕时)。默认为false
。
- 静态
- 动态
navigation.dispatch(
CommonActions.navigate('Profile', { user: 'jane' })
);
navigation.dispatch(
CommonActions.navigate('Profile', { user: 'jane' })
);
在堆栈导航器(堆栈 或 原生堆栈)中,使用屏幕名称调用 navigate
将具有以下行为
- 如果您已在具有相同名称的屏幕上,它将更新其参数,而不会推送新屏幕。
- 如果您在不同的屏幕上,它会将新屏幕推送到堆栈上。
- 如果指定了
getId
prop,并且堆栈中的另一个屏幕具有相同的 ID,它将导航到该屏幕并更新其参数。
高级用法
navigate
action 也可以接受一个对象作为参数,其中包含以下属性
name
- 字符串 - 当前或父导航器中屏幕的目标名称params
- 对象 - 用于目标路由的参数。merge
- 布尔值 - 参数是否应与现有路由参数合并,或替换它们(当导航到现有屏幕时)。默认为false
。path
- 字符串 - 与屏幕关联的路径(来自深度链接或通用链接)。
这主要在内部用于将路径与来自 URL 的屏幕关联。
reset
reset
action 允许将 导航状态 重置为给定状态。它接受以下参数
state
- 对象 - 要使用的新 导航状态 对象。
- 静态
- 动态
navigation.dispatch(
CommonActions.reset({
index: 1,
routes: [
{
name: 'Profile',
params: { user: 'jane', key: route.params.key },
},
{ name: 'Home' },
],
})
);
navigation.dispatch(
CommonActions.reset({
index: 1,
routes: [
{
name: 'Profile',
params: { user: 'jane', key: route.params.key },
},
{ name: 'Home' },
],
})
);
在 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,
});
});
请将导航器的状态对象视为内部对象,并且在小版本更新中可能会发生更改。除非您真的需要,否则请避免使用 导航状态 状态对象中的属性,除了 index
和 routes
。如果有一些功能您在不依赖状态对象的结构的情况下无法实现,请提出 issue。
使用 reset
重写历史记录
由于 reset
action 可以使用新的状态对象更新导航状态,因此它可以用于重写导航历史记录。但是,在大多数情况下,不建议重写历史记录以更改返回堆栈
- 它可能导致令人困惑的用户体验,因为用户期望能够返回到他们之前所在的屏幕。
- 当支持 Web 平台时,浏览器的历史记录仍将反映旧的导航状态,因此如果用户使用浏览器的后退按钮,他们将看到旧屏幕 - 导致 2 种不同的体验,具体取决于用户按下哪个后退按钮。
因此,如果您有这样的用例,请考虑其他方法 - 例如,一旦用户导航回已更改的屏幕,就更新历史记录。
goBack
goBack
action 创建器允许返回到历史记录中的上一个路由。它不接受任何参数。
- 静态
- 动态
navigation.dispatch(CommonActions.goBack());
navigation.dispatch(CommonActions.goBack());
如果您想从特定路由返回,您可以添加一个 source
属性,引用路由 key,以及一个 target
属性,引用包含该路由的导航器的 key
- 静态
- 动态
navigation.dispatch({
...CommonActions.goBack(),
source: route.key,
target: route?.params?.key,
});
navigation.dispatch({
...CommonActions.goBack(),
source: route.key,
target: route?.params?.key,
});
默认情况下,分发 action 的路由的 key 作为 source
属性传递,target
属性为 undefined
。
preload
preload
action 允许在导航到屏幕之前在后台预加载屏幕。它接受以下参数
name
- 字符串 - 当前或父导航器中屏幕的目标名称。params
- 对象 - 用于目标路由的参数。
- 静态
- 动态
navigation.dispatch(
CommonActions.preload('Profile', { user: 'jane' })
);
navigation.dispatch(
CommonActions.preload('Profile', { user: 'jane' })
);
预加载屏幕意味着屏幕将在后台渲染。屏幕中的所有组件都将被挂载,并且 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' }),
navigation.dispatch({
...CommonActions.setParams({ user: 'Wojtek' }),
如果您想为特定路由设置参数,您可以添加一个 source
属性,引用路由 key
- 静态
- 动态
navigation.dispatch({
...CommonActions.setParams({ user: 'Wojtek' }),
source: route.key,
});
navigation.dispatch({
...CommonActions.setParams({ user: 'Wojtek' }),
source: route.key,
});
如果 source
属性显式设置为 undefined
,它将为获得焦点的路由设置参数。