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

CommonActions 參考

導航動作是一個物件,至少包含一個 type 屬性。 在內部,動作可以由具有 getStateForAction 方法的路由器處理,以從現有的導航狀態返回新的狀態。

每個導航動作可以包含至少以下屬性

  • type (必填) - 一個字串,表示動作的名稱。
  • payload (選填) - 一個物件,包含關於動作的額外資訊。 例如,它將包含 nameparams 用於 navigate
  • source (選填) - 應該被視為動作來源的路由鍵。 這用於某些動作以確定將動作應用於哪個路由。 預設情況下,navigation.dispatch 會新增調度動作的路由鍵。
  • target (選填) - 應該應用動作的導航狀態的鍵。

重要的是要強調,當動作未處理時,調度導航動作不會拋出任何錯誤 (類似於當您調度一個未被 redux 中的 reducer 處理的動作時,並且沒有任何事情發生)。

通用動作

該函式庫在 CommonActions 命名空間下匯出多個動作建立器。 您應該使用這些動作建立器,而不是手動編寫動作物件。

navigate 動作允許導航到特定的路由。 它接受以下引數

  • name - 字串 - 當前或父導航器中螢幕的目的地名稱。
  • params - 物件 - 用於目的地路由的參數。
  • merge - 布林值 - 參數是否應該與現有的路由參數合併,還是替換它們 (當導航到現有的螢幕時)。 預設為 false
navigation.dispatch(
CommonActions.navigate('Profile', { user: 'jane' })
);
Snack 上試試看

在堆疊導航器 (堆疊原生堆疊) 中,使用螢幕名稱呼叫 navigate 將具有以下行為

  • 如果您已經在具有相同名稱的螢幕上,它將更新其參數,而不會推送新的螢幕。
  • 如果您在不同的螢幕上,它將把新的螢幕推送到堆疊上。
  • 如果指定了 getId 屬性,並且堆疊中的另一個螢幕具有相同的 ID,它將導航到該螢幕並更新其參數。
進階用法

navigate 動作也可以接受一個物件作為引數,具有以下屬性

  • name - 字串 - 當前或父導航器中螢幕的目的地名稱
  • params - 物件 - 用於目的地路由的參數。
  • merge - 布林值 - 參數是否應該與現有的路由參數合併,還是替換它們 (當導航到現有的螢幕時)。 預設為 false
  • path - 字串 - 與螢幕關聯的路徑 (來自深度連結或通用連結)。

這主要在內部用於將路徑與來自 URL 的螢幕關聯。

reset

reset 動作允許將導航狀態重置為給定的狀態。 它接受以下引數

navigation.dispatch(
CommonActions.reset({
index: 1,
routes: [
{
name: 'Profile',
params: { user: 'jane', key: route.params.key },
},
{ name: 'Home' },
],
})
);
Snack 上試試看

reset 中指定的狀態物件會將現有的導航狀態替換為新的狀態。 這表示如果您提供沒有鍵的新路由物件,或具有不同鍵的路由物件,它將移除這些路由的現有螢幕並新增新的螢幕。

如果您想保留現有的螢幕,但只想修改狀態,您可以將一個函式傳遞給 dispatch,您可以在其中取得現有的狀態。 然後您可以根據需要更改它 (確保不要變更現有的狀態,而是為您的更改建立新的狀態物件)。 並返回具有所需狀態的 reset 動作

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

navigation.dispatch((state) => {
// Remove all the screens after `Profile`
const index = state.routes.findIndex((r) => r.name === 'Profile');
const routes = state.routes.slice(0, index + 1);

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

將導航器的狀態物件視為內部物件,並可能在次要版本中更改。 避免使用導航狀態狀態物件中的屬性,除了 indexroutes,除非您真的需要它。 如果有些功能您無法在不依賴狀態物件的結構的情況下實現,請開啟一個 issue。

使用 reset 重寫歷史記錄

由於 reset 動作可以使用新的狀態物件更新導航狀態,因此可以用於重寫導航歷史記錄。 但是,在大多數情況下,不建議重寫歷史記錄以更改返回堆疊

  • 它可能會導致混亂的使用者體驗,因為使用者期望能夠返回他們之前所在的螢幕。
  • 當支援 Web 平台時,瀏覽器的歷史記錄仍然會反映舊的導航狀態,因此如果使用者使用瀏覽器的返回按鈕,他們將看到舊的螢幕 - 導致 2 種不同的體驗,具體取決於使用者按下哪個返回按鈕。

因此,如果您有這樣的用例,請考慮不同的方法 - 例如,一旦使用者導航回已更改的螢幕,就更新歷史記錄。

goBack

goBack 動作建立器允許返回歷史記錄中的上一個路由。 它不接受任何引數。

navigation.dispatch(CommonActions.goBack());
Snack 上試試看

如果您想從特定路由返回,您可以新增一個 source 屬性,指向路由鍵,以及一個 target 屬性,指向包含路由的導航器的 key

navigation.dispatch({
...CommonActions.goBack(),
source: route.key,
target: route?.params?.key,
});
Snack 上試試看

預設情況下,調度動作的路由鍵會作為 source 屬性傳遞,而 target 屬性為 undefined

preload

preload 動作允許在導航到螢幕之前在背景中預載螢幕。 它接受以下引數

  • name - 字串 - 當前或父導航器中螢幕的目的地名稱。
  • params - 物件 - 用於目的地路由的參數。
navigation.dispatch(
CommonActions.preload('Profile', { user: 'jane' })
);
Snack 上試試看

預載螢幕表示螢幕將在背景中渲染。 螢幕中的所有元件都將被掛載,並且將呼叫 useEffect hook。 當您想透過隱藏掛載重型元件或載入資料的延遲來提高感知效能時,這可能會很有用。

根據導航器的不同,preload 的運作方式可能會有所不同

  • 在堆疊導航器 (堆疊原生堆疊) 中,螢幕將在螢幕外渲染,並在您導航到螢幕時動畫進入。 如果指定了 getId,它將用於導航以識別預載的螢幕。
  • 在標籤或抽屜導航器 (底部標籤材質頂部標籤抽屜 等) 中,現有的螢幕將被渲染,就像 lazy 設定為 false 一樣。 在已經渲染的螢幕上呼叫 preload 將不會有任何效果。

當螢幕在堆疊導航器中預載時,它將有一些限制

  • 它無法調度導航動作 (例如 navigategoBack 等)。
  • 它無法使用 navigation.setOptions 更新選項。
  • 它無法監聽來自導航器的事件 (例如 focustabPress 等)。

一旦您導航到螢幕,navigation 物件將會更新。 因此,如果您在 useEffect hook 中有一個事件監聽器,並且依賴於 navigation,它將在導航到螢幕時新增任何監聽器

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

return () => {
unsubscribe();
};
}, [navigation]);

同樣,對於調度動作或更新選項,您可以先檢查螢幕是否處於焦點狀態,然後再執行此操作

if (navigation.isFocused()) {
navigation.setOptions({ title: 'Updated title' });
}

setParams

setParams 動作允許更新特定路由的參數。 它接受以下引數

  • params - 物件 - 必填 - 要合併到現有路由參數中的新參數。
navigation.dispatch({
...CommonActions.setParams({ user: 'Wojtek' }),
Snack 上試試看

如果您想為特定路由設定參數,您可以新增一個 source 屬性,指向路由鍵

navigation.dispatch({
...CommonActions.setParams({ user: 'Wojtek' }),
source: route.key,
});
Snack 上試試看

如果 source 屬性明確設定為 undefined,它將為焦點路由設定參數。