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

自訂路由器

路由器物件提供各種輔助方法,用於處理狀態和動作,一個 reducer 來更新狀態,以及一些動作建立器。

路由器負責處理通過呼叫導航物件方法派送的動作。如果路由器無法處理動作,它可以傳回 null,這將把動作傳播到其他路由器,直到它被處理。

您可以透過建立一個具有下列函數的物件來製作自己的路由器

  • type - 代表路由器類型字串,例如 'stack''tab''drawer' 等等。
  • getInitialState - 傳回導航器初始狀態的函數。接收具有 routeNamesrouteParamList 屬性的選項物件。
  • getRehydratedState - 函數,從給定的部分狀態重新還原完整的導航狀態。接收部分狀態物件和具有 routeNamesrouteParamList 屬性的選項物件。
  • getStateForRouteNamesChange - 函數,需要使用目前的狀態和已更新的路由名稱清單,並傳回新的狀態。接收狀態物件和具有 routeNamesrouteParamList 屬性的選項物件。
  • getStateForAction - 函數,需要使用目前的狀態和動作,以及具有 routeNamesrouteParamList 屬性的選項物件,並傳回新的狀態。如果無法處理動作,它應傳回 null
  • getStateForRouteFocus - 函數,需要使用目前的狀態和路由的 key,並傳回焦點在此路由時的新狀態。
  • shouldActionChangeFocus - 函數,用來判斷操作是否也應變更父導航程序裡的焦點。某些操作(例如 NAVIGATE)可以在父項中變更焦點。
  • actionCreators - 選擇性物件,含有動作產生器清單,例如 pushpop 等。這些動作產生器將用來將輔助函式新增到 navigation 物件,以發送這些動作。

範例

const router = {
type: 'tab',

getInitialState({ routeNames, routeParamList }) {
const index =
options.initialRouteName === undefined
? 0
: routeNames.indexOf(options.initialRouteName);

return {
stale: false,
type: 'tab',
key: shortid(),
index,
routeNames,
routes: routeNames.map(name => ({
name,
key: name,
params: routeParamList[name],
})),
};
},

getRehydratedState(partialState, { routeNames, routeParamList }) {
const state = partialState;

if (state.stale === false) {
return state as NavigationState;
}

const routes = state.routes
.filter(route => routeNames.includes(route.name))
.map(
route =>
({
...route,
key: route.key || `${route.name}-${shortid()}`,
params:
routeParamList[route.name] !== undefined
? {
...routeParamList[route.name],
...route.params,
}
: route.params,
} as Route<string>)
);

return {
stale: false,
type: 'tab',
key: shortid(),
index:
typeof state.index === 'number' && state.index < routes.length
? state.index
: 0,
routeNames,
routes,
};
},

getStateForRouteNamesChange(state, { routeNames }) {
const routes = state.routes.filter(route =>
routeNames.includes(route.name)
);

return {
...state,
routeNames,
routes,
index: Math.min(state.index, routes.length - 1),
};
},

getStateForRouteFocus(state, key) {
const index = state.routes.findIndex(r => r.key === key);

if (index === -1 || index === state.index) {
return state;
}

return { ...state, index };
},

getStateForAction(state, action) {
switch (action.type) {
case 'NAVIGATE': {
const index = state.routes.findIndex(
route => route.name === action.payload.name
);

if (index === -1) {
return null;
}

return { ...state, index };
}

default:
return BaseRouter.getStateForAction(state, action);
}
},

shouldActionChangeFocus() {
return false;
},
};

const SimpleRouter = () => router;

export default SimpleRouter;

內建路由器

此函式庫隨附幾個標準路由器

  • StackRouter
  • TabRouter
  • DrawerRouter

自訂路由器

你可以重複使用路由器並根據你的需求覆寫路由器函數,例如自訂現有動作的處理方式、新增其他動作等。

請參閱自訂導航程序,深入了解如何使用自訂路由器覆寫現有導航程序中的路由器。

自訂導航動作

假設你想加入自訂動作來清除記錄

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

const MyTabRouter = (options) => {
const router = TabRouter(options);

return {
...router,
getStateForAction(state, action, options) {
switch (action.type) {
case 'CLEAR_HISTORY':
return {
...state,
routeKeyHistory: [],
};
default:
return router.getStateForAction(state, action, options);
}
},

actionCreators: {
...router.actionCreators,
clearHistory() {
return { type: 'CLEAR_HISTORY' };
},
},
};
};

你不需要撰寫自訂路由器來處理自訂動作,而是可以改成傳遞函數至 dispatch。這樣會比較簡潔,推薦使用這種方式,而非覆寫路由器。

封鎖導航動作

有時你可能會想要禁止某幾種導航活動,這取決於你的路由。假設你想在 isEditingtrue 時禁止推播新畫面

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

const MyStackRouter = (options) => {
const router = StackRouter(options);

return {
...router,
getStateForAction(state, action, options) {
const result = router.getStateForAction(state, action, options);

if (
result != null &&
result.index > state.index &&
state.routes[state.index].params?.isEditing
) {
// Returning the current state means that the action has been handled, but we don't have a new state
return state;
}

return result;
},
};
};

如果你想要禁止返回,建議的方法是使用beforeRemove 事件