mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-04-29 21:05:29 +08:00
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:
@@ -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
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import * as React from 'react';
|
||||
|
||||
const DrawerOpenContext = React.createContext<boolean | null>(null);
|
||||
|
||||
export default DrawerOpenContext;
|
||||
7
packages/drawer/src/utils/DrawerStatusContext.tsx
Normal file
7
packages/drawer/src/utils/DrawerStatusContext.tsx
Normal file
@@ -0,0 +1,7 @@
|
||||
import * as React from 'react';
|
||||
|
||||
const DrawerStatusContext = React.createContext<'open' | 'closed' | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
export default DrawerStatusContext;
|
||||
@@ -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';
|
||||
}
|
||||
18
packages/drawer/src/utils/useDrawerStatus.tsx
Normal file
18
packages/drawer/src/utils/useDrawerStatus.tsx
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user