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

NavigationContainer

NavigationContainer 負責管理 app 狀態,以及將最高層導航器連結到 app 環境。

這項容器處理特定平台的整合,並提供各種實用功能

  1. linking prop 的深度連結整合。
  2. 針對 畫面追蹤狀態持續性 等發出狀態變更通知。
  3. 後使用 React Native 的 BackHandler API 來處理 Android 上的系統返回按鈕。

用量

import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';

const Stack = createNativeStackNavigator();

export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>{/* ... */}</Stack.Navigator>
</NavigationContainer>
);
}

Ref

也可以將 ref 附加到容器,以存取各種輔助方法,例如調度導航動作。當您無法使用 navigation prop(例如 Redux 中介軟體)時,這應該用於罕見情況。

範例

import {
NavigationContainer,
useNavigationContainerRef,
} from '@react-navigation/native';

function App() {
const navigationRef = useNavigationContainerRef(); // You can also use a regular ref with `React.useRef()`

return (
<View style={{ flex: 1 }}>
<Button onPress={() => navigationRef.navigate('Home')}>Go home</Button>
<NavigationContainer ref={navigationRef}>{/* ... */}</NavigationContainer>
</View>
);
}

如果您使用一般 ref 物件,請記住 ref 在某些情況下(例如啟用連結時)最初可能會為 null。若要確保 ref 已初始化,您可以使用 onReady 回呼在導航容器完成掛載時收到通知。

請參閱 在沒有 navigation prop 的情況下導航 指南以取得更多詳細資訊。

ref 上的方法

ref 物件包含所有常見的導覽方法,例如 navigategoBack 等。請參閱 CommonActions 的文件以取得更多詳細資料。

範例

navigationRef.navigate(name, params);

所有這些方法的反應,就像是在目前焦點畫面上進行呼叫一般。須注意,系統必須要有一個導覽器已完成渲染才能處理這些動作。

除了這些方法之外,ref 物件還包含下列特殊方法

isReady

isReady 方法會傳回 boolean,用以指示導覽樹是否就緒。當 NavigationContainer 包含至少一個導覽器,且所有導覽器都完成掛載,表示導覽樹已就緒。

這麼一來,你就可以用來判斷是否可以安全地傳送導覽動作而不發生錯誤。請參閱 處理初始化 以取得更多詳細資料。

resetRoot

透過 resetRoot 方法,你可以將導覽樹的狀態重新設定為指定的狀態物件

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

reset 方法不同的是,這個動作會施加在根導覽器,而不是目前焦點畫面的導覽器上。

getRootState

getRootState 方法會傳回 導覽狀態 物件,其中包含導覽樹中所有導覽器的導覽狀態

const state = navigationRef.getRootState();

請注意,如果目前沒有導覽器已完成渲染,傳回的 state 物件會是 undefined

getCurrentRoute

getCurrentRoute 方法會傳回整個導覽樹中目前焦點畫面的路線物件

const route = navigationRef.getCurrentRoute();

請注意,如果目前沒有導覽器已完成渲染,傳回的 route 物件會是 undefined

getCurrentOptions

getCurrentOptions 方法會傳回整個導覽樹中目前焦點畫面的選項

const options = navigationRef.getCurrentOptions();

請注意,如果目前沒有導覽器已完成渲染,傳回的 options 物件會是 undefined

addListener

透過 addListener 方法,你可以傾聽下列事件

state

當導航樹中任何導航器的導航狀態發生變更時會觸發事件

const unsubscribe = navigationRef.addListener('state', (e) => {
// You can get the raw navigation state (partial state object of the root navigator)
console.log(e.data.state);

// Or get the full state object with `getRootState()`
console.log(navigationRef.getRootState());
});

這類似於onStateChange方法。唯一的差別是e.data.state物件可能包含部分狀態物件,而onStateChange中的state參數則永遠會包含完整的狀態物件。

options

當導航樹中目前焦點所在的畫面選項變更時會觸發事件

const unsubscribe = navigationRef.addListener('options', (e) => {
// You can get the new options for the currently focused screen
console.log(e.data.options);
});

小工具

initialState

小工具,接受導航器的初始狀態。這有助於諸如深度連結、狀態持續等情況。

範例

<NavigationContainer initialState={initialState}>
{/* ... */}
</NavigationContainer>

提供自訂初始狀態物件會覆寫透過連結組態或瀏覽器 URL 獲得的初始狀態物件。如果你提供初始狀態物件,請確定沒有在網路傳遞它,且沒有深度連結要處理。

範例

const initialUrl = await Linking.getInitialURL();

if (Platform.OS !== 'web' && initialUrl == null) {
// Only restore state if there's no deep link and we're not on web
}

請參閱狀態持續指南,進一步瞭解如何持續並復原狀態。

onStateChange

警告

將導航器的狀態物件視為內部物件,可能會在次要版本中變更。請避免使用導航狀態狀態物件中的屬性,但indexroutes除外,除非你真的需要這麼做。若有某些你無法依靠狀態物件結構來達成功能,請開啟問題。

導航狀態每次變更時呼叫的功能。它會接收到新的導航狀態作為參數。

你可以使用它來追蹤焦點所在畫面、持續導航狀態等。

範例

<NavigationContainer
onStateChange={(state) => console.log('New state is', state)}
>
{/* ... */}
</NavigationContainer>

onReady

導航容器及其所有子項第一次完成安裝後呼叫的功能。你可以使用它來

範例

<NavigationContainer
onReady={() => console.log('Navigation container is ready')}
>
{/* ... */}
</NavigationContainer>

onUnhandledAction

此功能在任何導覽器都沒有處理導覽動作的情況下呼叫。

預設情況下,React Navigation 會在動作未處理時顯示僅限開發人員的錯誤訊息。您可以提供自訂功能來覆寫預設行為。

linking

連結整合的組態用於深層連結、瀏覽器中的 URL 支援等。

範例

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

function App() {
const linking = {
prefixes: ['https://mychat.com', 'mychat://'],
config: {
screens: {
Home: 'feed/:sort',
},
},
};

return (
<NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}>
{/* content */}
</NavigationContainer>
);
}

請參閱連結組態指南,瞭解有關如何組態深層連結與 URL 整合的更多詳細資訊。

選項

linking.prefixes

要處理的 URL 前置字元。您可以提供多個前置字元,以支援自訂範例,以及通用連結

只有符合這些前置字元的 URL 會被處理。解析前會從 URL 移除前置字元。

範例

<NavigationContainer
linking={{
prefixes: ['https://mychat.com', 'mychat://'],
config: {
screens: {
Chat: 'feed/:sort',
},
},
}}
>
{/* content */}
</NavigationContainer>

僅 iOS 和 Android 支援這個功能。

linking.config

組態參數用於調整路徑解析的方式。組態物件應該表示應用程式中導覽器的結構。

例如,如果我們在 Home 畫面中有 Catalog 畫面,並希望它處理「item/:id」模式

{
screens: {
Home: {
screens: {
Catalog: {
path: 'item/:id',
parse: {
id: Number,
},
},
},
},
}
}

解析選項可以是物件或字串

{
screens: {
Catalog: 'item/:id',
}
}

當指定字串時,等於提供 path 選項。

path 選項是一種與路徑比對的模式。任何從 : 開始的片段會被辨認為具有相同名稱的參數。例如,item/42 會被解析成 { name: 'item', params: { id: '42' } }

initialRouteName 選項可確保傳遞該處的路由名稱會存在於導覽器的狀態中,例如對於組態

{
screens: {
Home: {
initialRouteName: 'Feed',
screens: {
Catalog: {
path: 'item/:id',
parse: {
id: Number,
},
},
Feed: 'feed',
},
},
}
}

以及 URL:/item/42,狀態看起來會像這樣

{
routes: [
{
name: 'Home',
state: {
index: 1,
routes: [
{
name: 'Feed'
},
{
name: 'Catalog',
params: { id: 42 },
},
],
},
},
],
}

parse 選項控制參數的解析方式。在這裡,您可以提供要解析為關鍵字的參數名稱,以及一個會擷取參數的字串值並傳回已解析值的函式。

{
screens: {
Catalog: {
path: 'item/:id',
parse: {
id: id => parseInt(id, 10),
},
},
}
}

如果沒有提供用於解析參數的自訂函式,該參數會被解析為字串。

linking.enabled

選用的布林值,用於啟用或停用連結整合。如果指定 linking 屬性,則預設為 true

linking.getInitialURL

預設情況下,連結整合至 React Native 的 Linking API 中,並使用 Linking.getInitialURL() 提供深入連結的內建支援。不過,您可能也想要處理來自其他來源的連結,例如 Branch 或使用 Firebase 等發出的推播通知。

您可以提供自訂的 getInitialURL 函式,您可以在其中傳回我們該用作初始 URL 的連結。如果沒有要處理的 URL,getInitialURL 函式應傳回 string;否則傳回 undefined

例如,您可以執行類似以下動作來處理深入連結和 Firebase 通知

import messaging from '@react-native-firebase/messaging';

<NavigationContainer
linking={{
prefixes: ['https://mychat.com', 'mychat://'],
config: {
screens: {
Chat: 'feed/:sort',
},
},
async getInitialURL() {
// Check if app was opened from a deep link
const url = await Linking.getInitialURL();

if (url != null) {
return url;
}

// Check if there is an initial firebase notification
const message = await messaging().getInitialNotification();

// Get the `url` property from the notification which corresponds to a screen
// This property needs to be set on the notification payload when sending it
return message?.data?.url;
},
}}
>
{/* content */}
</NavigationContainer>;

這個選項在網頁上無法使用。

linking.subscribe

類似於 getInitialURL,您可以提供自訂的 subscribe 函式來處理所有接收到的連結,而不是預設的深入連結處理。subscribe 函式會接收一個偵聽器作為參數,如果有一個新的要處理的 URL,您可以用 URL 字串來呼叫它。它應傳回一個清除函式,讓您可以取消訂閱您設定的任何事件偵聽器。

例如,您可以執行類似以下動作來處理深入連結和 Firebase 通知

import messaging from '@react-native-firebase/messaging';

<NavigationContainer
linking={{
prefixes: ['https://mychat.com', 'mychat://'],
config: {
screens: {
Chat: 'feed/:sort',
},
},
subscribe(listener) {
const onReceiveURL = ({ url }: { url: string }) => listener(url);

// Listen to incoming links from deep linking
const subscription = Linking.addEventListener('url', onReceiveURL);

// Listen to firebase push notifications
const unsubscribeNotification = messaging().onNotificationOpenedApp(
(message) => {
const url = message.data?.url;

if (url) {
// Any custom logic to check whether the URL needs to be handled
//...

// Call the listener to let React Navigation handle the URL
listener(url);
}
}
);

return () => {
// Clean up the event listeners
subscription.remove();
unsubscribeNotification();
};
},
}}
>
{/* content */}
</NavigationContainer>

這個選項在網頁上無法使用。

linking.getStateFromPath

您可以選擇提供自己的實作,以覆寫 React Navigation 將連結剖析為狀態物件的方式。

範例

<NavigationContainer
linking={{
prefixes: ['https://mychat.com', 'mychat://'],
config: {
screens: {
Chat: 'feed/:sort',
},
},
getStateFromPath(path, config) {
// Return a state object here
// You can also reuse the default logic by importing `getStateFromPath` from `@react-navigation/native`
},
}}
>
{/* content */}
</NavigationContainer>
linking.getPathFromState

您可以選擇提供自己的實作,以覆寫 React Navigation 將狀態物件序列化為連結的方式。如果您指定了 getStateFromPath,則網頁支援需要這樣做。

範例

<NavigationContainer
linking={{
prefixes: ['https://mychat.com', 'mychat://'],
config: {
screens: {
Chat: 'feed/:sort',
},
},
getPathFromState(state, config) {
// Return a path string here
// You can also reuse the default logic by importing `getPathFromState` from `@react-navigation/native`
},
}}
>
{/* content */}
</NavigationContainer>

fallback

在我們解析深入連結時,使用為備用內容的 React Element。預設為 null

如果您有原生的載入畫面,請使用 onReady,而不是 fallback 屬性。

documentTitle

預設情況下,React Navigation 會在網頁上自動更新文件標題,以符合焦點畫面的 title 選項。您可以使用這個屬性停用或自訂它。它接受具有下列選項的設定物件

documentTitle.enabled

文件標題處理是否應啟用。預設為 true

documentTitle.formatter

如果您想要自訂標題文字,可以使用自訂格式化器。預設為

(options, route) => options?.title ?? route?.name;

範例

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

function App() {
return (
<NavigationContainer
documentTitle={{
formatter: (options, route) =>
`${options?.title ?? route?.name} - My Cool App`,
}}
>
{/* content */}
</NavigationContainer>
);
}

theme

自訂佈景主題供導覽元件(例如標頭、分頁欄等)使用。如需詳情以及使用說明,請參閱佈景主題指南

independent

警告

這是進階使用範例。除非您 100% 確定需要,否則請勿使用它。

這個導覽容器是否應該與父層容器獨立。如果這設定為 true,這個容器不能巢狀於另一個容器之中。將它設定為 true 會斷開任何子層導覽器與父層容器的連結,並禁止它們之間的導覽。

在典型的 React Native App 中,您可能不想將它設定為 true。這僅適用於導覽樹狀結構以其 mini-app 自行運作,而無需導覽至其外部的畫面。

如果您需要與第三方元件(例如模組或底端表單)整合,請避免使用這個。請考慮改用自訂導覽器