NavigationExperimental: Add documentation for NavigationStateUtils.
Summary: Add docs to NavigationStateUtils. Reviewed By: ericvicenti Differential Revision: D3679295 fbshipit-source-id: 26fc1e4f39af58e11572b74b150e08b3094e36c6
This commit is contained in:
parent
e106a4f094
commit
3a8c302ae8
|
@ -15,211 +15,201 @@ const invariant = require('fbjs/lib/invariant');
|
|||
|
||||
import type {
|
||||
NavigationRoute,
|
||||
NavigationState,
|
||||
NavigationState
|
||||
} from 'NavigationTypeDefinition';
|
||||
|
||||
/**
|
||||
* Utilities to perform atomic operation with navigate state and routes.
|
||||
*
|
||||
* ```javascript
|
||||
* const state1 = {key: 'page 1'};
|
||||
* const state2 = NavigationStateUtils.push(state1, {key: 'page 2'});
|
||||
* ```
|
||||
*/
|
||||
const NavigationStateUtils = {
|
||||
|
||||
/**
|
||||
* Gets a route by key
|
||||
*/
|
||||
function get(state: NavigationState, key: string): ?NavigationRoute {
|
||||
return state.routes.find(route => route.key === key) || null;
|
||||
}
|
||||
/**
|
||||
* Gets a route by key. If the route isn't found, returns `null`.
|
||||
*/
|
||||
get(state: NavigationState, key: string): ?NavigationRoute {
|
||||
return state.routes.find(route => route.key === key) || null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the first index at which a given route's key can be found in the
|
||||
* routes of the navigation state, or -1 if it is not present.
|
||||
*/
|
||||
function indexOf(state: NavigationState, key: string): number {
|
||||
return state.routes.map(route => route.key).indexOf(key);
|
||||
}
|
||||
/**
|
||||
* Returns the first index at which a given route's key can be found in the
|
||||
* routes of the navigation state, or -1 if it is not present.
|
||||
*/
|
||||
indexOf(state: NavigationState, key: string): number {
|
||||
return state.routes.map(route => route.key).indexOf(key);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns `true` at which a given route's key can be found in the
|
||||
* routes of the navigation state.
|
||||
*/
|
||||
function has(state: NavigationState, key: string): boolean {
|
||||
return !!state.routes.some(route => route.key === key);
|
||||
}
|
||||
/**
|
||||
* Returns `true` at which a given route's key can be found in the
|
||||
* routes of the navigation state.
|
||||
*/
|
||||
has(state: NavigationState, key: string): boolean {
|
||||
return !!state.routes.some(route => route.key === key);
|
||||
},
|
||||
|
||||
/**
|
||||
* Pushes a new route into the navigation state.
|
||||
* Note that this moves the index to the positon to where the last route in the
|
||||
* stack is at.
|
||||
*/
|
||||
function push(state: NavigationState, route: NavigationRoute): NavigationState {
|
||||
invariant(
|
||||
indexOf(state, route.key) === -1,
|
||||
'should not push route with duplicated key %s',
|
||||
route.key,
|
||||
);
|
||||
/**
|
||||
* Pushes a new route into the navigation state.
|
||||
* Note that this moves the index to the positon to where the last route in the
|
||||
* stack is at.
|
||||
*/
|
||||
push(state: NavigationState, route: NavigationRoute): NavigationState {
|
||||
invariant(
|
||||
NavigationStateUtils.indexOf(state, route.key) === -1,
|
||||
'should not push route with duplicated key %s',
|
||||
route.key,
|
||||
);
|
||||
|
||||
const routes = [
|
||||
...state.routes,
|
||||
route,
|
||||
];
|
||||
const routes = state.routes.slice();
|
||||
routes.push(route);
|
||||
|
||||
return {
|
||||
...state,
|
||||
index: routes.length - 1,
|
||||
routes,
|
||||
};
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
index: routes.length - 1,
|
||||
routes,
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Pops out a route from the navigation state.
|
||||
* Note that this moves the index to the positon to where the last route in the
|
||||
* stack is at.
|
||||
*/
|
||||
function pop(state: NavigationState): NavigationState {
|
||||
if (state.index <= 0) {
|
||||
// [Note]: Over-popping does not throw error. Instead, it will be no-op.
|
||||
return state;
|
||||
}
|
||||
const routes = state.routes.slice(0, -1);
|
||||
return {
|
||||
...state,
|
||||
index: routes.length - 1,
|
||||
routes,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the focused route of the navigation state by index.
|
||||
*/
|
||||
function jumpToIndex(state: NavigationState, index: number): NavigationState {
|
||||
if (index === state.index) {
|
||||
return state;
|
||||
}
|
||||
|
||||
invariant(!!state.routes[index], 'invalid index %s to jump to', index);
|
||||
|
||||
return {
|
||||
...state,
|
||||
index,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the focused route of the navigation state by key.
|
||||
*/
|
||||
function jumpTo(state: NavigationState, key: string): NavigationState {
|
||||
const index = indexOf(state, key);
|
||||
return jumpToIndex(state, index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the focused route to the previous route.
|
||||
*/
|
||||
function back(state: NavigationState): NavigationState {
|
||||
const index = state.index - 1;
|
||||
const route = state.routes[index];
|
||||
return route ? jumpToIndex(state, index) : state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the focused route to the next route.
|
||||
*/
|
||||
function forward(state: NavigationState): NavigationState {
|
||||
const index = state.index + 1;
|
||||
const route = state.routes[index];
|
||||
return route ? jumpToIndex(state, index) : state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a route by a key.
|
||||
* Note that this moves the index to the positon to where the new route in the
|
||||
* stack is at.
|
||||
*/
|
||||
function replaceAt(
|
||||
state: NavigationState,
|
||||
key: string,
|
||||
route: NavigationRoute,
|
||||
): NavigationState {
|
||||
const index = indexOf(state, key);
|
||||
return replaceAtIndex(state, index, route);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a route by a index.
|
||||
* Note that this moves the index to the positon to where the new route in the
|
||||
* stack is at.
|
||||
*/
|
||||
function replaceAtIndex(
|
||||
state: NavigationState,
|
||||
index: number,
|
||||
route: NavigationRoute,
|
||||
): NavigationState {
|
||||
invariant(
|
||||
!!state.routes[index],
|
||||
'invalid index %s for replacing route %s',
|
||||
index,
|
||||
route.key,
|
||||
);
|
||||
|
||||
if (state.routes[index] === route) {
|
||||
return state;
|
||||
}
|
||||
|
||||
const routes = state.routes.slice();
|
||||
routes[index] = route;
|
||||
|
||||
return {
|
||||
...state,
|
||||
index,
|
||||
routes,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all routes.
|
||||
* Note that this moves the index to the positon to where the last route in the
|
||||
* stack is at if the param `index` isn't provided.
|
||||
*/
|
||||
function reset(
|
||||
state: NavigationState,
|
||||
routes: Array<NavigationRoute>,
|
||||
index?: number,
|
||||
): NavigationState {
|
||||
invariant(
|
||||
routes.length && Array.isArray(routes),
|
||||
'invalid routes to replace',
|
||||
);
|
||||
|
||||
const nextIndex: number = index === undefined ? routes.length - 1 : index;
|
||||
|
||||
if (state.routes.length === routes.length && state.index === nextIndex) {
|
||||
const compare = (route, ii) => routes[ii] === route;
|
||||
if (state.routes.every(compare)) {
|
||||
/**
|
||||
* Pops out a route from the navigation state.
|
||||
* Note that this moves the index to the positon to where the last route in the
|
||||
* stack is at.
|
||||
*/
|
||||
pop(state: NavigationState): NavigationState {
|
||||
if (state.index <= 0) {
|
||||
// [Note]: Over-popping does not throw error. Instead, it will be no-op.
|
||||
return state;
|
||||
}
|
||||
}
|
||||
const routes = state.routes.slice(0, -1);
|
||||
return {
|
||||
...state,
|
||||
index: routes.length - 1,
|
||||
routes,
|
||||
};
|
||||
},
|
||||
|
||||
invariant(!!routes[nextIndex], 'invalid index %s to reset', nextIndex);
|
||||
/**
|
||||
* Sets the focused route of the navigation state by index.
|
||||
*/
|
||||
jumpToIndex(state: NavigationState, index: number): NavigationState {
|
||||
if (index === state.index) {
|
||||
return state;
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
index: nextIndex,
|
||||
routes,
|
||||
};
|
||||
}
|
||||
invariant(!!state.routes[index], 'invalid index %s to jump to', index);
|
||||
|
||||
const NavigationStateUtils = {
|
||||
back,
|
||||
forward,
|
||||
get: get,
|
||||
has,
|
||||
indexOf,
|
||||
jumpTo,
|
||||
jumpToIndex,
|
||||
pop,
|
||||
push,
|
||||
replaceAt,
|
||||
replaceAtIndex,
|
||||
reset,
|
||||
return {
|
||||
...state,
|
||||
index,
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the focused route of the navigation state by key.
|
||||
*/
|
||||
jumpTo(state: NavigationState, key: string): NavigationState {
|
||||
const index = NavigationStateUtils.indexOf(state, key);
|
||||
return NavigationStateUtils.jumpToIndex(state, index);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the focused route to the previous route.
|
||||
*/
|
||||
back(state: NavigationState): NavigationState {
|
||||
const index = state.index - 1;
|
||||
const route = state.routes[index];
|
||||
return route ? NavigationStateUtils.jumpToIndex(state, index) : state;
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the focused route to the next route.
|
||||
*/
|
||||
forward(state: NavigationState): NavigationState {
|
||||
const index = state.index + 1;
|
||||
const route = state.routes[index];
|
||||
return route ? NavigationStateUtils.jumpToIndex(state, index) : state;
|
||||
},
|
||||
|
||||
/**
|
||||
* Replace a route by a key.
|
||||
* Note that this moves the index to the positon to where the new route in the
|
||||
* stack is at.
|
||||
*/
|
||||
replaceAt(
|
||||
state: NavigationState,
|
||||
key: string,
|
||||
route: NavigationRoute,
|
||||
): NavigationState {
|
||||
const index = NavigationStateUtils.indexOf(state, key);
|
||||
return NavigationStateUtils.replaceAtIndex(state, index, route);
|
||||
},
|
||||
|
||||
/**
|
||||
* Replace a route by a index.
|
||||
* Note that this moves the index to the positon to where the new route in the
|
||||
* stack is at.
|
||||
*/
|
||||
replaceAtIndex(
|
||||
state: NavigationState,
|
||||
index: number,
|
||||
route: NavigationRoute,
|
||||
): NavigationState {
|
||||
invariant(
|
||||
!!state.routes[index],
|
||||
'invalid index %s for replacing route %s',
|
||||
index,
|
||||
route.key,
|
||||
);
|
||||
|
||||
if (state.routes[index] === route) {
|
||||
return state;
|
||||
}
|
||||
|
||||
const routes = state.routes.slice();
|
||||
routes[index] = route;
|
||||
|
||||
return {
|
||||
...state,
|
||||
index,
|
||||
routes,
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Resets all routes.
|
||||
* Note that this moves the index to the positon to where the last route in the
|
||||
* stack is at if the param `index` isn't provided.
|
||||
*/
|
||||
reset(
|
||||
state: NavigationState,
|
||||
routes: Array<NavigationRoute>,
|
||||
index?: number,
|
||||
): NavigationState {
|
||||
invariant(
|
||||
routes.length && Array.isArray(routes),
|
||||
'invalid routes to replace',
|
||||
);
|
||||
|
||||
const nextIndex: number = index === undefined ? routes.length - 1 : index;
|
||||
|
||||
if (state.routes.length === routes.length && state.index === nextIndex) {
|
||||
const compare = (route, ii) => routes[ii] === route;
|
||||
if (state.routes.every(compare)) {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
invariant(!!routes[nextIndex], 'invalid index %s to reset', nextIndex);
|
||||
|
||||
return {
|
||||
...state,
|
||||
index: nextIndex,
|
||||
routes,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = NavigationStateUtils;
|
||||
|
|
Loading…
Reference in New Issue