create-expo-cljs-app
Version:
Create a react native application with Expo and Shadow-CLJS!
81 lines (72 loc) • 2.63 kB
JavaScript
import * as React from 'react';
import { CommonActions } from '@react-navigation/routers';
/**
* Hook to cache navigation objects for each screen in the navigator.
* It's important to cache them to make sure navigation objects don't change between renders.
* This lets us apply optimizations like `React.memo` to minimize re-rendering screens.
*/
export default function useNavigationCache({
state,
getState,
navigation,
setOptions,
router,
emitter
}) {
// Cache object which holds navigation objects for each screen
// We use `React.useMemo` instead of `React.useRef` coz we want to invalidate it when deps change
// In reality, these deps will rarely change, if ever
const cache = React.useMemo(() => ({
current: {}
}), // eslint-disable-next-line react-hooks/exhaustive-deps
[getState, navigation, setOptions, router, emitter]);
const actions = { ...router.actionCreators,
...CommonActions
};
cache.current = state.routes.reduce((acc, route) => {
const previous = cache.current[route.key];
if (previous) {
// If a cached navigation object already exists, reuse it
acc[route.key] = previous;
} else {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const {
emit,
...rest
} = navigation;
const dispatch = action => {
const payload = typeof action === 'function' ? action(getState()) : action;
navigation.dispatch(typeof payload === 'object' && payload != null ? {
source: route.key,
...payload
} : payload);
};
const helpers = Object.keys(actions).reduce((acc, name) => {
// @ts-expect-error: name is a valid key, but TypeScript is dumb
acc[name] = (...args) => dispatch(actions[name](...args));
return acc;
}, {});
acc[route.key] = { ...rest,
...helpers,
...emitter.create(route.key),
dispatch,
setOptions: options => setOptions(o => ({ ...o,
[route.key]: { ...o[route.key],
...options
}
})),
isFocused: () => {
const state = getState();
if (state.routes[state.index].key !== route.key) {
return false;
} // If the current screen is focused, we also need to check if parent navigator is focused
// This makes sure that we return the focus state in the whole tree, not just this navigator
return navigation ? navigation.isFocused() : true;
}
};
}
return acc;
}, {});
return cache.current;
}
//# sourceMappingURL=useNavigationCache.js.map