Add refocus event and fix child navigation caching

This commit is contained in:
Brent Vatne
2018-10-22 16:57:51 -07:00
parent e8fb25e9eb
commit 70c69307c4
4 changed files with 79 additions and 43 deletions

View File

@@ -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);
}
};
}

View File

@@ -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;

View 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;
}

View File

@@ -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 = {