导航生命周期
在上一节中,我们使用了具有两个屏幕(Home
和 Details
)的堆栈导航器,并学习了如何使用 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 向订阅这些事件的屏幕组件触发事件。我们可以监听 focus
和 blur
事件来分别了解屏幕何时进入焦点或失焦。
¥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. -
你还可以使用
useFocusEffect
或useIsFocused
钩子。¥You may also use the
useFocusEffect
oruseIsFocused
hooks.