mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-02-10 09:13:43 +08:00
Add refocus event and fix child navigation caching
This commit is contained in:
@@ -10,6 +10,7 @@ export default function getChildEventSubscriber(addListener, key) {
|
||||
const didFocusSubscribers = new Set();
|
||||
const willBlurSubscribers = new Set();
|
||||
const didBlurSubscribers = new Set();
|
||||
const refocusSubscribers = new Set();
|
||||
|
||||
const removeAll = () => {
|
||||
[
|
||||
@@ -18,6 +19,7 @@ export default function getChildEventSubscriber(addListener, key) {
|
||||
didFocusSubscribers,
|
||||
willBlurSubscribers,
|
||||
didBlurSubscribers,
|
||||
refocusSubscribers,
|
||||
].forEach(set => set.clear());
|
||||
|
||||
upstreamSubscribers.forEach(subs => subs && subs.remove());
|
||||
@@ -35,6 +37,8 @@ export default function getChildEventSubscriber(addListener, key) {
|
||||
return willBlurSubscribers;
|
||||
case 'didBlur':
|
||||
return didBlurSubscribers;
|
||||
case 'refocus':
|
||||
return refocusSubscribers;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
@@ -60,11 +64,17 @@ export default function getChildEventSubscriber(addListener, key) {
|
||||
'didFocus',
|
||||
'willBlur',
|
||||
'didBlur',
|
||||
'refocus',
|
||||
'action',
|
||||
];
|
||||
|
||||
const upstreamSubscribers = upstreamEvents.map(eventName =>
|
||||
addListener(eventName, payload => {
|
||||
if (eventName === 'refocus') {
|
||||
emit(eventName, payload);
|
||||
return;
|
||||
}
|
||||
|
||||
const { state, lastState, action } = payload;
|
||||
const lastRoutes = lastState && lastState.routes;
|
||||
const routes = state && state.routes;
|
||||
@@ -157,5 +167,12 @@ export default function getChildEventSubscriber(addListener, key) {
|
||||
};
|
||||
return { remove };
|
||||
},
|
||||
emit(eventName, payload) {
|
||||
if (eventName !== 'refocus') {
|
||||
console.error(`navigation.emit only supports the 'refocus' event currently.`);
|
||||
return;
|
||||
}
|
||||
emit(eventName, payload);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import getChildEventSubscriber from './getChildEventSubscriber';
|
||||
import getChildRouter from './getChildRouter';
|
||||
import getNavigationActionCreators from './routers/getNavigationActionCreators';
|
||||
import getChildrenNavigationCache from './getChildrenNavigationCache';
|
||||
|
||||
const createParamGetter = route => (paramName, defaultValue) => {
|
||||
const params = route.params;
|
||||
@@ -13,9 +14,7 @@ const createParamGetter = route => (paramName, defaultValue) => {
|
||||
};
|
||||
|
||||
function getChildNavigation(navigation, childKey, getCurrentParentNavigation) {
|
||||
const children =
|
||||
navigation._childrenNavigation || (navigation._childrenNavigation = {});
|
||||
|
||||
const children = getChildrenNavigationCache(navigation);
|
||||
const childRoute = navigation.state.routes.find(r => r.key === childKey);
|
||||
|
||||
if (!childRoute) {
|
||||
@@ -66,47 +65,48 @@ function getChildNavigation(navigation, childKey, getCurrentParentNavigation) {
|
||||
getParam: createParamGetter(childRoute),
|
||||
};
|
||||
return children[childKey];
|
||||
} else {
|
||||
const childSubscriber = getChildEventSubscriber(
|
||||
navigation.addListener,
|
||||
childKey
|
||||
);
|
||||
|
||||
children[childKey] = {
|
||||
...actionHelpers,
|
||||
|
||||
state: childRoute,
|
||||
router: childRouter,
|
||||
actions: actionCreators,
|
||||
getParam: createParamGetter(childRoute),
|
||||
|
||||
getChildNavigation: grandChildKey =>
|
||||
getChildNavigation(children[childKey], grandChildKey, () => {
|
||||
const nav = getCurrentParentNavigation();
|
||||
return nav && nav.getChildNavigation(childKey);
|
||||
}),
|
||||
|
||||
isFocused: () => {
|
||||
const currentNavigation = getCurrentParentNavigation();
|
||||
if (!currentNavigation) {
|
||||
return false;
|
||||
}
|
||||
const { routes, index } = currentNavigation.state;
|
||||
if (!currentNavigation.isFocused()) {
|
||||
return false;
|
||||
}
|
||||
if (routes[index].key === childKey) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
dispatch: navigation.dispatch,
|
||||
getScreenProps: navigation.getScreenProps,
|
||||
dangerouslyGetParent: getCurrentParentNavigation,
|
||||
addListener: childSubscriber.addListener,
|
||||
emit: childSubscriber.emit,
|
||||
};
|
||||
return children[childKey];
|
||||
}
|
||||
|
||||
const childSubscriber = getChildEventSubscriber(
|
||||
navigation.addListener,
|
||||
childKey
|
||||
);
|
||||
|
||||
children[childKey] = {
|
||||
...actionHelpers,
|
||||
|
||||
state: childRoute,
|
||||
router: childRouter,
|
||||
actions: actionCreators,
|
||||
getParam: createParamGetter(childRoute),
|
||||
|
||||
getChildNavigation: grandChildKey =>
|
||||
getChildNavigation(children[childKey], grandChildKey, () => {
|
||||
const nav = getCurrentParentNavigation();
|
||||
return nav && nav.getChildNavigation(childKey);
|
||||
}),
|
||||
|
||||
isFocused: () => {
|
||||
const currentNavigation = getCurrentParentNavigation();
|
||||
if (!currentNavigation) {
|
||||
return false;
|
||||
}
|
||||
const { routes, index } = currentNavigation.state;
|
||||
if (!currentNavigation.isFocused()) {
|
||||
return false;
|
||||
}
|
||||
if (routes[index].key === childKey) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
dispatch: navigation.dispatch,
|
||||
getScreenProps: navigation.getScreenProps,
|
||||
dangerouslyGetParent: getCurrentParentNavigation,
|
||||
addListener: childSubscriber.addListener,
|
||||
};
|
||||
return children[childKey];
|
||||
}
|
||||
|
||||
export default getChildNavigation;
|
||||
|
||||
17
packages/core/src/getChildrenNavigationCache.js
Normal file
17
packages/core/src/getChildrenNavigationCache.js
Normal file
@@ -0,0 +1,17 @@
|
||||
export default function getChildrenNavigationCache(navigation) {
|
||||
if (!navigation) {
|
||||
return {};
|
||||
}
|
||||
|
||||
let childrenNavigationCache = navigation._childrenNavigation
|
||||
? navigation._childrenNavigation
|
||||
: {};
|
||||
let childKeys = navigation.state.routes.map(route => route.key);
|
||||
Object.keys(childrenNavigationCache).forEach(cacheKey => {
|
||||
if (!childKeys.includes(cacheKey)) {
|
||||
delete childrenNavigationCache[cacheKey];
|
||||
}
|
||||
});
|
||||
|
||||
return childrenNavigationCache;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import getNavigationActionCreators from './routers/getNavigationActionCreators';
|
||||
import getChildNavigation from './getChildNavigation';
|
||||
import getChildrenNavigationCache from './getChildrenNavigationCache';
|
||||
|
||||
export default function getNavigation(
|
||||
router,
|
||||
@@ -38,6 +39,7 @@ export default function getNavigation(
|
||||
};
|
||||
},
|
||||
dangerouslyGetParent: () => null,
|
||||
_childrenNavigation: getChildrenNavigationCache(getCurrentNavigation())
|
||||
};
|
||||
|
||||
const actionCreators = {
|
||||
|
||||
Reference in New Issue
Block a user