跳到主要內容
版本:6.x

導覽事件

你可以聆聽由 React 導覽發出的各種事件,以取得特定事件的通知,並在某些情況下取代預設動作。有幾個核心事件,例如 focusblur 等(如下所述),適用於每個導覽器,以及僅適用於特定導覽器的導覽器特定事件。

除了核心事件之外,每個導覽器都可以發出自己的自訂事件。例如,堆疊導覽器會發出 transitionStarttransitionEnd 事件,而標籤導覽器會發出 tabPress 事件等。你可以在個別導覽器的文件中找到有關已發出事件的詳細資訊。

核心事件

以下是每個導覽器中提供的事件

focus

當畫面獲得焦點時,會發出此事件。

對於大多數情況來說,useFocusEffect 掛鉤可能比手動加入監聽器更合適。請參閱此指南,以取得更多詳細資訊,用於判定應使用哪個 API。

blur

當畫面失去焦點時,會發出此事件。

state

導航狀態變更時,此事件會發出。此事件在事件資料 (event.data.state) 中接收導航狀態。

beforeRemove

使用者離開畫面時,此事件會發出,有可能會阻止使用者離開

監控事件

有多種方式可以監控導航中的事件。以事件監聽器註冊的每個回呼接收事件物件作為引數。事件物件包含幾個屬性

  • 資料 - 導航傳遞的其他事件相關資料。若沒有傳遞資料,則會是 未定義
  • 目標 - 應接收事件的畫面路由金鑰。對於某些事件,若事件與特定畫面無關,這可能會是 未定義
  • preventDefault - 對於某些事件,事件物件上可能會有 preventDefault 方法。呼叫此方法會阻止事件執行的預設動作 (例如在 tabPress 中切換分頁)。只有某些事件支援防止動作,例如 tabPress,而並非所有事件都適用。

你可以用下列 API 監控事件

在畫面中,你可以用 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.Navigatorid 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。它會收到 navigationroute 作為引數。

範例

<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>