Skip to main content
Version: 6.x

导航生命周期

在上一节中,我们使用了具有两个屏幕(HomeDetails)的堆栈导航器,并学习了如何使用 navigation.navigate('RouteName') 在路由之间导航。

¥In a previous section, we worked with a stack navigator that has two screens (Home and Details) and learned how to use navigation.navigate('RouteName') to navigate between the routes.

在这方面的一个重要问题是:当我们离开或回到 Home 时,会发生什么?路由如何发现用户正在离开或返回?

¥An important question in this context is: what happens with Home when we navigate away from it, or when we come back to it? How does a route find out that a user is leaving it or coming back to it?

如果你从 Web 后台进入 React-navigation,你可能会假设当用户从路由 A 导航到路由 B 时,A 将卸载(调用其 componentWillUnmount),并且当用户返回时 A 将再次挂载。虽然这些 React 生命周期方法仍然有效并且在 React-navigation 中使用,但它们的用法与 Web 不同。这是由移动导航更复杂的需求驱动的。

¥If you are coming to react-navigation from a web background, you may assume that when user navigates from route A to route B, A will unmount (its componentWillUnmount is called) and A will mount again when user comes back to it. While these React lifecycle methods are still valid and are used in react-navigation, their usage differs from the web. This is driven by more complex needs of mobile navigation.

示例场景

¥Example scenario

考虑一个带有屏幕 A 和 B 的堆栈导航器。导航到 A 后,调用其 componentDidMount。当压入 B 时,它的 componentDidMount 也会被调用,但 A 仍然安装在堆栈上,因此不会调用它的 componentWillUnmount

¥Consider a stack navigator with screens A and B. After navigating to A, its componentDidMount is called. When pushing B, its componentDidMount is also called, but A remains mounted on the stack and its componentWillUnmount is therefore not called.

当从 B 返回到 A 时,B 的 componentWillUnmount 被调用,但 A 的 componentDidMount 没有被调用,因为 A 始终保持挂载状态。

¥When going back from B to A, componentWillUnmount of B is called, but componentDidMount of A is not because A remained mounted the whole time.

与其他导航器(结合)也可以观察到类似的结果。考虑一个带有两个选项卡的选项卡导航器,其中每个选项卡都是一个堆栈导航器:

¥Similar results can be observed (in combination) with other navigators as well. Consider a tab navigator with two tabs, where each tab is a stack navigator:

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 的导航状态已保留!

¥We start on the HomeScreen and navigate to DetailsScreen. Then we use the tab bar to switch to the SettingsScreen and navigate to ProfileScreen. After this sequence of operations is done, all 4 of the screens are mounted! If you use the tab bar to switch back to the HomeStack, you'll notice you'll be presented with the DetailsScreen - the navigation state of the HomeStack has been preserved!

React 导航生命周期事件

¥React Navigation lifecycle events

现在我们了解了 React 生命周期方法在 React Navigation 中的工作原理,让我们回答一开始提出的问题:"我们如何发现用户正在离开(模糊)它或返回它(焦点)?"

¥Now that we understand how React lifecycle methods work in React Navigation, let's answer the question we asked at the beginning: "How do we find out that a user is leaving (blur) it or coming back to it (focus)?"

React Navigation 向订阅这些事件的屏幕组件触发事件。我们可以监听 focusblur 事件来分别了解屏幕何时进入焦点或失焦。

¥React Navigation emits events to screen components that subscribe to them. We can listen to focus and blur events to know when a screen comes into focus or goes out of focus respectively.

示例:

¥Example:

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

return unsubscribe;
}, [navigation]);

return <ProfileContent />;
}

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

¥See Navigation events for more details on the available events and the API usage.

我们可以使用 useFocusEffect 钩子来执行副作用,而不是手动添加事件监听器。它就像 React 的 useEffect 钩子,但它与导航生命周期相关。

¥Instead of adding event listeners manually, we can use the useFocusEffect hook to perform side effects. It's like React's useEffect hook, but it ties into the navigation lifecycle.

示例:

¥Example:

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 钩子,它返回一个布尔值来指示屏幕是否聚焦。

¥If you want to render different things based on if the screen is focused or not, you can use the useIsFocused hook which returns a boolean indicating whether the screen is focused.

概括

¥Summary

  • 虽然 React 的生命周期方法仍然有效,但 React Navigation 添加了更多可以通过 navigation 属性订阅的事件。

    ¥While React's lifecycle methods are still valid, React Navigation adds more events that you can subscribe to through the navigation prop.

  • 你还可以使用 useFocusEffectuseIsFocused 钩子。

    ¥You may also use the useFocusEffect or useIsFocused hooks.