refactor: don't use a boolean for drawer status

BREAKING CHANGE: Drawer status is now a union ('open', 'closed') instead of a boolean. This will let us implement more types of status in future.

Following this the following exports have been renamed as well:
- getIsDrawerOpenFromState -> getDrawerStatusFromState
- useIsDrawerOpen -> useDrawerStatus
This commit is contained in:
Satyajit Sahoo
2021-01-15 12:49:20 +01:00
parent 79a85a431c
commit cda6397b89
9 changed files with 84 additions and 47 deletions

View File

@@ -17,8 +17,8 @@ export { default as DrawerContentScrollView } from './views/DrawerContentScrollV
*/
export { default as DrawerGestureContext } from './utils/DrawerGestureContext';
export { default as getIsDrawerOpenFromState } from './utils/getIsDrawerOpenFromState';
export { default as useIsDrawerOpen } from './utils/useIsDrawerOpen';
export { default as getDrawerStatusFromState } from './utils/getDrawerStatusFromState';
export { default as useDrawerStatus } from './utils/useDrawerStatus';
/**
* Types

View File

@@ -1,5 +0,0 @@
import * as React from 'react';
const DrawerOpenContext = React.createContext<boolean | null>(null);
export default DrawerOpenContext;

View File

@@ -0,0 +1,7 @@
import * as React from 'react';
const DrawerStatusContext = React.createContext<'open' | 'closed' | undefined>(
undefined
);
export default DrawerStatusContext;

View File

@@ -3,14 +3,18 @@ import type {
ParamListBase,
} from '@react-navigation/native';
export default function getIsDrawerOpenFromState(
export default function getDrawerStatusFromState(
state: DrawerNavigationState<ParamListBase>
): boolean {
) {
if (state.history == null) {
throw new Error(
"Couldn't find the drawer status in the state object. Is it a valid state object of drawer navigator?"
);
}
return state.history.some((it) => it.type === 'drawer');
const entry = state.history.find((it) => it.type === 'drawer') as
| { type: 'drawer'; status: 'open' }
| undefined;
return entry?.status ?? 'closed';
}

View File

@@ -0,0 +1,18 @@
import * as React from 'react';
import DrawerStatusContext from './DrawerStatusContext';
/**
* Hook to detect if the drawer's status in a parent navigator.
* Returns 'open' if the drawer is open, 'closed' if the drawer is closed.
*/
export default function useDrawerStatus() {
const drawerStatus = React.useContext(DrawerStatusContext);
if (drawerStatus === undefined) {
throw new Error(
"Couldn't find a drawer. Is your component inside a drawer navigator?"
);
}
return drawerStatus;
}

View File

@@ -1,17 +0,0 @@
import * as React from 'react';
import DrawerOpenContext from './DrawerOpenContext';
/**
* Hook to detect if the drawer is open in a parent navigator.
*/
export default function useIsDrawerOpen() {
const isDrawerOpen = React.useContext(DrawerOpenContext);
if (typeof isDrawerOpen !== 'boolean') {
throw new Error(
"Couldn't find a drawer. Is your component inside a drawer navigator?"
);
}
return isDrawerOpen;
}

View File

@@ -25,9 +25,9 @@ import ResourceSavingScene from './ResourceSavingScene';
import Header from './Header';
import DrawerContent from './DrawerContent';
import Drawer from './Drawer';
import DrawerOpenContext from '../utils/DrawerOpenContext';
import DrawerStatusContext from '../utils/DrawerStatusContext';
import DrawerPositionContext from '../utils/DrawerPositionContext';
import getIsDrawerOpenFromState from '../utils/getIsDrawerOpenFromState';
import getDrawerStatusFromState from '../utils/getDrawerStatusFromState';
import type {
DrawerDescriptorMap,
DrawerNavigationConfig,
@@ -97,7 +97,7 @@ function DrawerViewBase({
const { colors } = useTheme();
const isDrawerOpen = getIsDrawerOpenFromState(state);
const drawerStatus = getDrawerStatusFromState(state);
const handleDrawerOpen = React.useCallback(() => {
navigation.dispatch({
@@ -116,7 +116,7 @@ function DrawerViewBase({
React.useEffect(() => {
let subscription: NativeEventSubscription | undefined;
if (isDrawerOpen) {
if (drawerStatus === 'open') {
// We only add the subscription when drawer opens
// This way we can make sure that the subscription is added as late as possible
// This will make sure that our handler will run first when back button is pressed
@@ -128,7 +128,7 @@ function DrawerViewBase({
}
return () => subscription?.remove();
}, [handleDrawerClose, isDrawerOpen, navigation, state.key]);
}, [handleDrawerClose, drawerStatus, navigation, state.key]);
const focusedRouteKey = state.routes[state.index].key;
@@ -200,9 +200,9 @@ function DrawerViewBase({
};
return (
<DrawerOpenContext.Provider value={isDrawerOpen}>
<DrawerStatusContext.Provider value={drawerStatus}>
<Drawer
open={isDrawerOpen}
open={drawerStatus !== 'closed'}
gestureEnabled={gestureEnabled}
swipeEnabled={swipeEnabled}
onOpen={handleDrawerOpen}
@@ -241,7 +241,7 @@ function DrawerViewBase({
keyboardDismissMode={keyboardDismissMode}
dimensions={dimensions}
/>
</DrawerOpenContext.Provider>
</DrawerStatusContext.Provider>
);
}