CommonActions 參考
導航動作是一個物件,至少包含一個 type
屬性。 在內部,動作可以由具有 getStateForAction
方法的路由器處理,以從現有的導航狀態返回新的狀態。
每個導航動作可以包含至少以下屬性
type
(必填) - 一個字串,表示動作的名稱。payload
(選填) - 一個物件,包含關於動作的額外資訊。 例如,它將包含name
和params
用於navigate
。source
(選填) - 應該被視為動作來源的路由鍵。 這用於某些動作以確定將動作應用於哪個路由。 預設情況下,navigation.dispatch
會新增調度動作的路由鍵。target
(選填) - 應該應用動作的導航狀態的鍵。
重要的是要強調,當動作未處理時,調度導航動作不會拋出任何錯誤 (類似於當您調度一個未被 redux 中的 reducer 處理的動作時,並且沒有任何事情發生)。
通用動作
該函式庫在 CommonActions
命名空間下匯出多個動作建立器。 您應該使用這些動作建立器,而不是手動編寫動作物件。
navigate
navigate
動作允許導航到特定的路由。 它接受以下引數
name
- 字串 - 當前或父導航器中螢幕的目的地名稱。params
- 物件 - 用於目的地路由的參數。merge
- 布林值 - 參數是否應該與現有的路由參數合併,還是替換它們 (當導航到現有的螢幕時)。 預設為false
。
- 靜態
- 動態
navigation.dispatch(
CommonActions.navigate('Profile', { user: 'jane' })
);
navigation.dispatch(
CommonActions.navigate('Profile', { user: 'jane' })
);
在堆疊導航器 (堆疊 或 原生堆疊) 中,使用螢幕名稱呼叫 navigate
將具有以下行為
- 如果您已經在具有相同名稱的螢幕上,它將更新其參數,而不會推送新的螢幕。
- 如果您在不同的螢幕上,它將把新的螢幕推送到堆疊上。
- 如果指定了
getId
屬性,並且堆疊中的另一個螢幕具有相同的 ID,它將導航到該螢幕並更新其參數。
進階用法
navigate
動作也可以接受一個物件作為引數,具有以下屬性
name
- 字串 - 當前或父導航器中螢幕的目的地名稱params
- 物件 - 用於目的地路由的參數。merge
- 布林值 - 參數是否應該與現有的路由參數合併,還是替換它們 (當導航到現有的螢幕時)。 預設為false
。path
- 字串 - 與螢幕關聯的路徑 (來自深度連結或通用連結)。
這主要在內部用於將路徑與來自 URL 的螢幕關聯。
reset
reset
動作允許將導航狀態重置為給定的狀態。 它接受以下引數
state
- 物件 - 要使用的新導航狀態物件。
- 靜態
- 動態
navigation.dispatch(
CommonActions.reset({
index: 1,
routes: [
{
name: 'Profile',
params: { user: 'jane', key: route.params.key },
},
{ name: 'Home' },
],
})
);
navigation.dispatch(
CommonActions.reset({
index: 1,
routes: [
{
name: 'Profile',
params: { user: 'jane', key: route.params.key },
},
{ name: 'Home' },
],
})
);
在 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,
});
});
將導航器的狀態物件視為內部物件,並可能在次要版本中更改。 避免使用導航狀態狀態物件中的屬性,除了 index
和 routes
,除非您真的需要它。 如果有些功能您無法在不依賴狀態物件的結構的情況下實現,請開啟一個 issue。
使用 reset
重寫歷史記錄
由於 reset
動作可以使用新的狀態物件更新導航狀態,因此可以用於重寫導航歷史記錄。 但是,在大多數情況下,不建議重寫歷史記錄以更改返回堆疊
- 它可能會導致混亂的使用者體驗,因為使用者期望能夠返回他們之前所在的螢幕。
- 當支援 Web 平台時,瀏覽器的歷史記錄仍然會反映舊的導航狀態,因此如果使用者使用瀏覽器的返回按鈕,他們將看到舊的螢幕 - 導致 2 種不同的體驗,具體取決於使用者按下哪個返回按鈕。
因此,如果您有這樣的用例,請考慮不同的方法 - 例如,一旦使用者導航回已更改的螢幕,就更新歷史記錄。
goBack
goBack
動作建立器允許返回歷史記錄中的上一個路由。 它不接受任何引數。
- 靜態
- 動態
navigation.dispatch(CommonActions.goBack());
navigation.dispatch(CommonActions.goBack());
如果您想從特定路由返回,您可以新增一個 source
屬性,指向路由鍵,以及一個 target
屬性,指向包含路由的導航器的 key
- 靜態
- 動態
navigation.dispatch({
...CommonActions.goBack(),
source: route.key,
target: route?.params?.key,
});
navigation.dispatch({
...CommonActions.goBack(),
source: route.key,
target: route?.params?.key,
});
預設情況下,調度動作的路由鍵會作為 source
屬性傳遞,而 target
屬性為 undefined
。
preload
preload
動作允許在導航到螢幕之前在背景中預載螢幕。 它接受以下引數
name
- 字串 - 當前或父導航器中螢幕的目的地名稱。params
- 物件 - 用於目的地路由的參數。
- 靜態
- 動態
navigation.dispatch(
CommonActions.preload('Profile', { user: 'jane' })
);
navigation.dispatch(
CommonActions.preload('Profile', { user: 'jane' })
);
預載螢幕表示螢幕將在背景中渲染。 螢幕中的所有元件都將被掛載,並且將呼叫 useEffect
hook。 當您想透過隱藏掛載重型元件或載入資料的延遲來提高感知效能時,這可能會很有用。
根據導航器的不同,preload
的運作方式可能會有所不同
- 在堆疊導航器 (堆疊、原生堆疊) 中,螢幕將在螢幕外渲染,並在您導航到螢幕時動畫進入。 如果指定了
getId
,它將用於導航以識別預載的螢幕。 - 在標籤或抽屜導航器 (底部標籤、材質頂部標籤、抽屜 等) 中,現有的螢幕將被渲染,就像
lazy
設定為false
一樣。 在已經渲染的螢幕上呼叫preload
將不會有任何效果。
當螢幕在堆疊導航器中預載時,它將有一些限制
- 它無法調度導航動作 (例如
navigate
、goBack
等)。 - 它無法使用
navigation.setOptions
更新選項。 - 它無法監聽來自導航器的事件 (例如
focus
、tabPress
等)。
一旦您導航到螢幕,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' }),
navigation.dispatch({
...CommonActions.setParams({ user: 'Wojtek' }),
如果您想為特定路由設定參數,您可以新增一個 source
屬性,指向路由鍵
- 靜態
- 動態
navigation.dispatch({
...CommonActions.setParams({ user: 'Wojtek' }),
source: route.key,
});
navigation.dispatch({
...CommonActions.setParams({ user: 'Wojtek' }),
source: route.key,
});
如果 source
屬性明確設定為 undefined
,它將為焦點路由設定參數。