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

导航生命周期

在上一节中,我们使用了一个包含两个屏幕(HomeDetails)的堆栈导航器,并学习了如何使用 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 向订阅它们的屏幕组件发出事件。我们可以监听 focusblur 事件,以了解屏幕何时进入焦点或失去焦点。

示例

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 属性订阅的事件。
  • 您也可以使用 useFocusEffectuseIsFocused 钩子。