導覽事件
你可以聆聽由 React 導覽發出的各種事件,以取得特定事件的通知,並在某些情況下取代預設動作。有幾個核心事件,例如 focus
、blur
等(如下所述),適用於每個導覽器,以及僅適用於特定導覽器的導覽器特定事件。
除了核心事件之外,每個導覽器都可以發出自己的自訂事件。例如,堆疊導覽器會發出 transitionStart
和 transitionEnd
事件,而標籤導覽器會發出 tabPress
事件等。你可以在個別導覽器的文件中找到有關已發出事件的詳細資訊。
核心事件
以下是每個導覽器中提供的事件
focus
當畫面獲得焦點時,會發出此事件。
對於大多數情況來說,useFocusEffect
掛鉤可能比手動加入監聽器更合適。請參閱此指南,以取得更多詳細資訊,用於判定應使用哪個 API。
blur
當畫面失去焦點時,會發出此事件。
state
導航狀態變更時,此事件會發出。此事件在事件資料 (event.data.state
) 中接收導航狀態。
beforeRemove
使用者離開畫面時,此事件會發出,有可能會阻止使用者離開。
監控事件
有多種方式可以監控導航中的事件。以事件監聽器註冊的每個回呼接收事件物件作為引數。事件物件包含幾個屬性
資料
- 導航傳遞的其他事件相關資料。若沒有傳遞資料,則會是未定義
。目標
- 應接收事件的畫面路由金鑰。對於某些事件,若事件與特定畫面無關,這可能會是未定義
。preventDefault
- 對於某些事件,事件物件上可能會有preventDefault
方法。呼叫此方法會阻止事件執行的預設動作 (例如在tabPress
中切換分頁)。只有某些事件支援防止動作,例如tabPress
,而並非所有事件都適用。
你可以用下列 API 監控事件
navigation.addListener
在畫面中,你可以用 addListener
方法針對 navigation
prop 新增監聽器。addListener
方法有 2 個引數:事件類型和事件呼叫的回呼。其會回傳一個可以用來取消訂閱事件的函數。
範例
const unsubscribe = navigation.addListener('tabPress', (e) => {
// Prevent default action
e.preventDefault();
});
一般來說,你會在函數元件的 React.useEffect
中新增事件監聽器。例如
function Profile({ navigation }) {
React.useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
// do something
});
return unsubscribe;
}, [navigation]);
return <ProfileContent />;
}
unsubscribe
函數可以做為 effect 中的清理函數回傳。
對於類別元件,你可以在 componentDidMount
生命週期方法中新增事件,並在 componentWillUnmount
中取消訂閱
class Profile extends React.Component {
componentDidMount() {
this._unsubscribe = navigation.addListener('focus', () => {
// do something
});
}
componentWillUnmount() {
this._unsubscribe();
}
render() {
// Content of the component
}
}
請注意,你只能用 addListener
監控直接導航的事件。例如,如果你嘗試在堆疊內的畫面中新增監聽器,而堆疊又巢狀在分頁中,則其不會取得 tabPress
事件。如果你需要監控父導航中的事件,你可以使用 navigation.getParent
來取得父導航的導航 prop 參照,並新增監聽器。
const unsubscribe = navigation
.getParent('MyTabs')
.addListener('tabPress', (e) => {
// Do something
});
在此,'MyTabs'
指的是你要監控其事件的父 Tab.Navigator
中 id
prop 傳遞的值。
Screen
上的 listeners
屬性
有時你可能想要從定義 navigator 的元件中加入一個 listener,而不是在畫面中加入。你可以使用 Screen
元件上的 listeners
屬性來加入 listener。listeners
屬性會使用一個物件,其中事件名稱是鍵,listener callback 是值。
範例
<Tab.Screen
name="Chat"
component={Chat}
listeners={{
tabPress: (e) => {
// Prevent default action
e.preventDefault();
},
}}
/>
你也可以傳遞一個會傳回有 listener 的物件的 callback。它會收到 navigation
和 route
作為引數。
範例
<Tab.Screen
name="Chat"
component={Chat}
listeners={({ navigation, route }) => ({
tabPress: (e) => {
// Prevent default action
e.preventDefault();
// Do something with the `navigation` object
navigation.navigate('AnotherPlace');
},
})}
/>
navigator 上的 screenListeners
屬性
你可以傳遞一個稱為 screenListeners
的屬性給 navigator 元件,並在其中為這個 navigator 中所有畫面的事件指定 listener。如果你想要聆聽不論在畫面上的哪個特定事件,或是想要聆聽會發送至所有畫面的常見事件(例如 state
),這會很有用。
範例
<Stack.Navigator
screenListeners={{
state: (e) => {
// Do something with the state
console.log('state changed', e.data);
},
}}
>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="Profile" component={ProfileScreen} />
</Stack.Navigator>
類似於 listeners
,你也可以傳遞一個函式給 screenListeners
。這個函式會收到每個畫面的 navigation
屬性 和 route
屬性。如果你需要存取 navigation
物件,這會很有用。
<Tab.Navigator
screenListeners={({ navigation }) => ({
state: (e) => {
// Do something with the state
console.log('state changed', e.data);
// Do something with the `navigation` object
if (!navigation.canGoBack()) {
console.log("we're on the initial screen");
}
},
})}
>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="Profile" component={ProfileScreen} />
</Tab.Navigator>