跳到主內容
版本:6.x

導覽屬性參考

App 中的每個 screen 元件都會自動提供 navigation 屬性。此屬性包含各種方便的函式,用來發送導覽動作。它會以下列方式顯示

  • navigation
    • navigate - 前往指定的畫面,此行為會依導航器而有所不同
    • goBack - 回到上一個畫面,此行為會在堆疊中使用時關閉當前畫面
    • reset - 使用指定的狀態取代導航器的導覽狀態
    • setParams - 將新參數併入路線的參數
    • dispatch - 傳送動作物件,以更新導覽狀態
    • setOptions - 更新畫面的選項
    • isFocused - 檢查畫面是否已開啟
    • canGoBack - 檢查是否可以從當前的畫面返回
    • getState - 取得導航器的導覽狀態
    • getParent - 取得父畫面(若有)的導覽物件
    • addListener - 訂閱畫面的事件
    • removeListener - 取消訂閱畫面的事件

重點是,將 navigation 屬性傳遞給 所有 元件並非必須;只有 screen 元件會自動接收這個屬性!React Navigation 在這裡不會施展任何魔法。例如,假設您要定義 MyBackButton 元件並將它呈現為畫面元件的子項,您將無法在上面存取 navigation 屬性。但是,如果您想在任何元件中存取 navigation 屬性,可以使用 useNavigation 勾子。

setParams/setOptions 等只能在 useEffect/useLayoutEffect/componentDidMount/componentDidUpdate 等中呼叫。不能在 render 時或在建構函數中呼叫。

navigation 屬性上有幾個額外的函式,依據目前的導覽器種類而定。

如果導覽器是堆疊導覽器,navigategoBack 提供了幾個替代方案,您可以使用任何您偏好的方案。函式如下:

  • navigation
    • replace - 以新的畫面取代目前的畫面
    • push - 將新的畫面推送到堆疊
    • pop - 回到堆疊
    • popToTop - 前往堆疊最上方

請參閱 堆疊導覽器說明原生的堆疊導覽器說明,以取得這些方法的詳細資訊。

如果導覽器是索引標籤導覽器,則下列內容也可用:

  • navigation
    • jumpTo - 前往索引標籤導覽器中的特定畫面

請參閱 底部索引標籤導覽器說明Material Top Tab 導覽器說明Material Bottom Tab 導覽器說明,以取得這些方法的詳細資訊。

如果導覽器是抽屜導覽器,則下列內容也可用:

  • navigation
    • jumpTo - 前往抽屜導覽器中的特定畫面
    • openDrawer - 開啟抽屜
    • closeDrawer - 關閉抽屜
    • toggleDrawer - 切換狀態,例如從關閉變開啟,反之亦然

請參閱 抽屜導覽器說明,以取得這些方法的詳細資訊。

常見的 API 參考

您與 navigation 屬性互動的大部分時間將會涉及 navigategoBacksetParams

navigate 方法讓我們可以導覽至 App 中的其他畫面。傳入下列參數:

navigation.navigate(name, params)

  • name - 已定義在某處的目的地畫面名稱
  • params - 傳遞給目標路由的參數。
function HomeScreen({ navigation: { navigate } }) {
return (
<View>
<Text>This is the home screen of the app</Text>
<Button
onPress={() =>
navigate('Profile', { names: ['Brent', 'Satya', 'Michaś'] })
}
title="Go to Brent's profile"
/>
</View>
);
}

原生堆疊導航器 中,使用螢幕名稱呼叫 navigate 將會產生不同的行為,具體取決於螢幕是否已經存在。如果螢幕已存在於堆疊的歷程中,它將返回到該螢幕並移除其後的任何螢幕。如果螢幕不存在,則它將推送一個新的螢幕。

例如,如果你有一個歷程堆疊 Home > Profile > Settings,然後你呼叫 navigate(Profile),則最終的螢幕將會是 Home > Profile,因為它會返回到 Profile 並移除 Settings 螢幕。

預設情況下,螢幕會透過其名稱進行識別。不過你也可以透過使用 getId prop 來自訂,使其考慮參數。

例如,假設你為 Profile 螢幕指定了一個 getId prop

<Tab.Screen
name={Profile}
component={ProfileScreen}
getId={({ params }) => params.userId}
/>

現在,如果你有一個歷程堆疊 Home > Profile (userId: bob) > Settings,然後你呼叫 navigate(Profile, { userId: 'alice' }),則最終的螢幕將會是 Home > Profile (userId: bob) > Settings > Profile (userId: alice),因為它將會新增一個新的 Profile 螢幕,原因是找不到相符的螢幕。

goBack

goBack 方法讓我們返回導航器中的前一螢幕。

預設情況下,goBack 將從其所呼叫的螢幕返回

function ProfileScreen({ navigation: { goBack } }) {
return (
<View>
<Button onPress={() => goBack()} title="Go back from ProfileScreen" />
</View>
);
}

從特定螢幕返回

考慮以下的導航堆疊歷程

navigation.navigate({ name: SCREEN, key: SCREEN_KEY_A });
navigation.navigate({ name: SCREEN, key: SCREEN_KEY_B });
navigation.navigate({ name: SCREEN, key: SCREEN_KEY_C });
navigation.navigate({ name: SCREEN, key: SCREEN_KEY_D });

現在你在螢幕 D 上,並且想要返回螢幕 A(彈出 D、C 和 B)。然後你可以使用 navigate

navigation.navigate({ key: SCREEN_KEY_A }); // will go to screen A FROM screen D

或者,由於螢幕 A 位於堆疊的最上面,因此你可以使用 navigation.popToTop()

reset

reset 方法讓我們替換導航狀態為一個新的狀態

navigation.reset({
index: 0,
routes: [{ name: 'Profile' }],
});

reset 中指定的狀態物件會以新的物件取代現有的 導航狀態,也就是說它會移除現有的螢幕並新增新的螢幕。如果你在變更狀態時想要保留現有的螢幕,則可以改用透過 CommonActions.resetdispatch 進行。

警告

將 navigator 的狀態物件視為內部物件,且在較小版本中可能有所變更。避免使用 navigation state 狀態物件中的屬性,但對於 indexroutes 例外,除非你真的需要它。如果你在不依賴狀態物件結構的情況下,無法執行某些功能,請開啟問題。

setParams

setParams 方法讓我們更新目前畫面的參數(route.params)。setParams 的運作方式就像 React 的 setState - 會將所提供的參數物件與目前參數進行淺層合併。

function ProfileScreen({ navigation: { setParams } }) {
return (
<Button
onPress={() =>
setParams({
friends:
route.params.friends[0] === 'Brent'
? ['Wojciech', 'Szymon', 'Jakub']
: ['Brent', 'Satya', 'Michaś'],
title:
route.params.title === "Brent's Profile"
? "Lucy's Profile"
: "Brent's Profile",
})
}
title="Swap title and friends"
/>
);
}

setOptions

setOptions 方法讓我們從元件內設定畫面選項。如果我們需要使用元件的 props、狀態或內容來設定畫面,這項功能會很有用。

function ProfileScreen({ navigation, route }) {
const [value, onChangeText] = React.useState(route.params.title);

React.useEffect(() => {
navigation.setOptions({
title: value === '' ? 'No title' : value,
});
}, [navigation, value]);

return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<TextInput
style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
onChangeText={onChangeText}
value={value}
/>
<Button title="Go back" onPress={() => navigation.goBack()} />
</View>
);
}

於此處指定的任何選項均會與定義畫面時指定的選項進行淺層合併。

在使用 navigation.setOptions 時,我們建議在畫面的 options 道具中指定一個佔位符,並使用 navigation.setOptions 更新它。如此一來,可確保更新選項的延遲對使用者而言不會很明顯。這也讓它能用於延遲載入畫面。

你也可以使用 React.useLayoutEffect 來減少更新選項時的延遲。不過,如果你支援網頁並使用伺服器端渲染,我們不建議這樣做。

備註

navigation.setOptions 的目的是提供一種方式,讓你在必要時更新既有選項。它並非畫面中 options 道具的替代方案。請確定僅在絕對必要的時後,才慎重地使用 navigation.setOptions

畫面可以使用 addListener 方法在 navigation 道具上新增監聽器。例如,要監聽 focus 事件

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

return unsubscribe;
}, [navigation]);

return <ProfileContent />;
}

參閱 導覽事件,以瞭解有關可用事件和 API 使用方式的更多詳細資訊。

isFocused

此方法讓我們檢查畫面目前是否處於焦點中。如果畫面處於焦點中,則傳回 true,否則傳回 false

const isFocused = navigation.isFocused();

當值變更時此方法不會重新渲染畫面,主要用於回呼。你可能想要使用 useIsFocused 而不是直接使用此方法,它會回傳一個布林值 prop 來指示畫面是否已聚焦。

進階 API 參考

dispatch 函式較少用到,但當你無法利用現有方法(如 navigategoBack 等)時,它是一個很好的逃生艙口。我們建議避免經常使用 dispatch 方法,除非絕對必要。

dispatch

dispatch 方法讓我們可以傳送一個導覽動作物件,它決定如何更新 導覽狀態。所有導覽函式(如 navigate)都會在背後使用 dispatch

請注意,如果你要調度動作,你應該使用此程式庫提供的動作產生器,而不是直接撰寫動作物件。

請查看 導覽動作文件 以取得可用動作的完整清單。

import { CommonActions } from '@react-navigation/native';

navigation.dispatch(
CommonActions.navigate({
name: 'Profile',
params: {},
})
);

在調度動作物件時,你還可以指定幾個額外屬性

  • source - 路線的鍵應該視為動作的來源。例如,replace 動作會用提供的鍵取代路線。預設情況下,它會使用調度動作的路線鍵。你可以明確傳遞 undefined 來覆寫此行為。
  • target - 動作應套用的 導覽狀態 的鍵。預設情況下,如果導航器未處理動作,動作會冒泡到其他導航器。如果指定 target,如果具有相同鍵的導航器未處理動作,動作不會冒泡。

範例

import { CommonActions } from '@react-navigation/native';

navigation.dispatch({
...CommonActions.navigate('Profile'),
source: 'someRoutekey',
target: 'someStatekey',
});

自訂動作產生器

也可以將動作產生器函式傳遞給 dispatch。該函式會收到目前狀態,並需要回傳要使用的導覽動作物件

import { CommonActions } from '@react-navigation/native';

navigation.dispatch((state) => {
// Add the home route to the start of the stack
const routes = [{ name: 'Home' }, ...state.routes];

return CommonActions.reset({
...state,
routes,
index: routes.length - 1,
});
});

你可以使用此功能來建立自己的協助程式,並在你的應用程式中使用。以下是一個範例,用於在最後一個畫面之前插入一個畫面

import { CommonActions } from '@react-navigation/native';

const insertBeforeLast = (routeName, params) => (state) => {
const routes = [
...state.routes.slice(0, -1),
{ name: routeName, params },
state.routes[state.routes.length - 1],
];

return CommonActions.reset({
...state,
routes,
index: routes.length - 1,
});
};

然後像這樣使用

navigation.dispatch(insertBeforeLast('Home'));

canGoBack

此方法會回傳一個布林值,表示目前導航器或任何父導航器中是否有任何導覽歷程記錄可用。你可以使用此方法來檢查是否可以呼叫 navigation.goBack()

if (navigation.canGoBack()) {
navigation.goBack();
}

不建議使用此方法來呈現內容,因為這不會觸發重新呈現。這只能在呼叫、事件監聽器等內部使用。

getParent

此方法會傳回嵌套目前瀏覽器之父瀏覽器裡面的瀏覽器 prop。例如,如果你有一個堆疊瀏覽器和一個分頁瀏覽器,嵌套在堆疊瀏覽器內,那麼你可以使用分頁瀏覽器中的畫面中的 getParent 來取得從堆疊瀏覽器傳遞過來的瀏覽器 prop。

它接受一個 ID 選擇性參數,用來參考特定父瀏覽器。例如,你的畫面嵌套在多層之下,在某處 Drawer 瀏覽器的 id prop 為 "LeftDrawer",你可以直接參考它而不用多次呼叫 getParent

要對瀏覽器使用 ID,首先傳遞一個獨特的 id prop

<Drawer.Navigator id="LeftDrawer">{/* .. */}</Drawer.Navigator>

然後在使用 getParent 時,修改為

// Avoid this
const drawerNavigation = navigation.getParent().getParent();

// ...

drawerNavigation?.openDrawer();

你能這樣做

// Do this
const drawerNavigation = navigation.getParent('LeftDrawer');

// ...

drawerNavigation?.openDrawer();

這樣的作法可以讓元件不需要了解瀏覽器的巢狀結構。因此,非常建議在使用 getParent 時使用一個 id

如果沒有相符的父瀏覽器,這個方法會傳回 undefined。使用這個方法時請務必隨時檢查是否有 undefined

getState

警告

將 navigator 的狀態物件視為內部物件,且在較小版本中可能有所變更。避免使用 navigation state 狀態物件中的屬性,但對於 indexroutes 例外,除非你真的需要它。如果你在不依賴狀態物件結構的情況下,無法執行某些功能,請開啟問題。

此方法傳回包含畫面的瀏覽器狀態物件。取得瀏覽器狀態在非常少見的情況下可能會有用。你很有可能不需要使用此方法。如果你真的要使用,請確定你有一個很好的理由。

如果你需要狀態來呈現內容,你應該使用 useNavigationState 而非此方法。