导航生命周期
在上一节中,我们使用了一个包含两个屏幕(Home
和 Details
)的堆栈导航器,并学习了如何使用 navigation.navigate('RouteName')
在路由之间导航。
在这种情况下,一个重要的问题是:当我们从 Home
导航到其他路由时,或者当我们返回 Home
时,Home
会发生什么?路由如何知道用户正在离开它或返回它?
如果您来自 web 背景,您可能认为当用户从路由 A
导航到路由 B
时,A
将卸载(其 componentWillUnmount
被调用),并且当用户返回 A
时,A
将重新挂载。虽然这些 React 生命周期方法仍然有效,并且在 react-navigation 中使用,但它们的用法与 web 不同。这是由移动导航更复杂的需求驱动的。
示例场景
考虑一个包含屏幕 A 和 B 的堆栈导航器。在导航到 A 后,会调用其 componentDidMount
。当推送 B 时,也会调用其 componentDidMount
,但 A 仍然保留在堆栈中,因此不会调用其 componentWillUnmount
。
从 B 返回到 A 时,会调用 B 的 componentWillUnmount
,但不会调用 A 的 componentDidMount
,因为 A 一直保持挂载状态。
类似的结果也可以在其他导航器中观察到(组合使用)。考虑一个带有两个选项卡的选项卡导航器,其中每个选项卡都是一个堆栈导航器。
function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="First">
{() => (
<SettingsStack.Navigator>
<SettingsStack.Screen
name="Settings"
component={SettingsScreen}
/>
<SettingsStack.Screen name="Profile" component={ProfileScreen} />
</SettingsStack.Navigator>
)}
</Tab.Screen>
<Tab.Screen name="Second">
{() => (
<HomeStack.Navigator>
<HomeStack.Screen name="Home" component={HomeScreen} />
<HomeStack.Screen name="Details" component={DetailsScreen} />
</HomeStack.Navigator>
)}
</Tab.Screen>
</Tab.Navigator>
</NavigationContainer>
);
}
我们从 HomeScreen
开始,导航到 DetailsScreen
。然后我们使用选项卡栏切换到 SettingsScreen
并导航到 ProfileScreen
。完成此操作序列后,所有 4 个屏幕都已挂载!如果您使用选项卡栏切换回 HomeStack
,您会注意到您将看到 DetailsScreen
- HomeStack
的导航状态已保留!
React Navigation 生命周期事件
现在我们了解了 React Navigation 中 React 生命周期方法的工作原理,让我们回答我们在开头提出的问题:“我们如何知道用户正在离开(模糊)它或返回到它(聚焦)?”
React Navigation 向订阅它们的屏幕组件发出事件。我们可以监听 focus
和 blur
事件,以了解屏幕何时进入焦点或失去焦点。
示例
function Profile({ navigation }) {
React.useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
// Screen was focused
// Do something
});
return unsubscribe;
}, [navigation]);
return <ProfileContent />;
}
有关可用事件和 API 用法的更多详细信息,请参阅 导航事件。
除了手动添加事件监听器,我们还可以使用 useFocusEffect
钩子来执行副作用。它类似于 React 的 useEffect
钩子,但它与导航生命周期相关联。
示例
import { useFocusEffect } from '@react-navigation/native';
function Profile() {
useFocusEffect(
React.useCallback(() => {
// Do something when the screen is focused
return () => {
// Do something when the screen is unfocused
// Useful for cleanup functions
};
}, [])
);
return <ProfileContent />;
}
如果您想根据屏幕是否处于焦点状态来渲染不同的内容,可以使用 useIsFocused
钩子,它返回一个布尔值,指示屏幕是否处于焦点状态。
总结
- 虽然 React 的生命周期方法仍然有效,但 React Navigation 添加了更多您可以通过
navigation
属性订阅的事件。 - 您也可以使用
useFocusEffect
或useIsFocused
钩子。