導覽生命週期
在上一個章節,我們使用兩個畫面(首頁
和明細
)的堆疊導覽工具,並學習如何使用 navigation.navigate('RouteName')
在路線之間進行導覽。
在此脈絡中,一個重要問題是:當我們離開 首頁
或返回 首頁
時,會發生什麼事?路線如何得知使用者離開或返回該路線?
如果您來自網頁背景而開始使用 react-navigation,可能會假設當使用者從 A
路線導覽至 B
路線時,A
會卸載(呼叫 componentWillUnmount
),而在使用者返回 A
路線時,A
會再次載入。雖然這些 React 生命週期方法仍然有效,並用於 react-navigation 中,但其用法與網頁不同。這是由行動導覽更複雜的需求驅動的。
範例場景
考慮一個具有 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 導航生命週期事件
現在我們了解 React 生命週期方法如何在 React 導航中運作,讓我們來回答一開始提出的問題:「我們如何得知使用者離開(模糊)它或返回到這個(焦點)畫面?」
React 導航會發出事件到訂閱這些事件的畫面元件。我們可以監聽 focus
和 blur
事件,以分別得知畫面何時進入焦點或離開焦點。
範例
function Profile({ navigation }) {
React.useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
// Screen was focused
// Do something
});
return unsubscribe;
}, [navigation]);
return <ProfileContent />;
}
參閱導航事件,以取得關於可用事件和 API 使用的更多詳情。
我們可以使用 useFocusEffect
hook 來執行附帶效應,而非手動加入事件監聽。它就像 React 的 useEffect
hook,但它與導航生命週期有關。
範例
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
hook,它會傳回一個布林值表示畫面是否取得焦點。
摘要
- 儘管 React 的生命週期方法仍然有效,但 React 導航新增了更多你可以透過
navigation
屬性訂閱的事件。 - 你也可以使用
useFocusEffect
或useIsFocused
hooks。