Skip to content

Commit

Permalink
fix: properly handle history if drawer is open by default
Browse files Browse the repository at this point in the history
  • Loading branch information
satya164 committed Oct 9, 2021
1 parent 8e7ba69 commit de2d4e4
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 74 deletions.
1 change: 1 addition & 0 deletions example/src/Screens/MasterDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ export default function DrawerScreen({ navigation, ...rest }: Props) {

return (
<Drawer.Navigator
backBehavior="none"
defaultStatus="open"
drawerContent={(props) => <CustomDrawerContent {...props} />}
screenOptions={{
Expand Down
18 changes: 11 additions & 7 deletions packages/drawer/src/navigators/createDrawerNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
DrawerNavigationState,
DrawerRouter,
DrawerRouterOptions,
DrawerStatus,
ParamListBase,
useNavigationBuilder,
} from '@react-navigation/native';
Expand All @@ -29,7 +30,7 @@ type Props = DefaultNavigatorOptions<

function DrawerNavigator({
initialRouteName,
defaultStatus,
defaultStatus: customDefaultStatus,
backBehavior,
children,
screenListeners,
Expand Down Expand Up @@ -92,6 +93,13 @@ function DrawerNavigator({
);
}

const defaultStatus: DrawerStatus =
customDefaultStatus !== undefined
? customDefaultStatus
: openByDefault
? 'open'
: 'closed';

const { state, descriptors, navigation, NavigationContent } =
useNavigationBuilder<
DrawerNavigationState<ParamListBase>,
Expand All @@ -101,12 +109,7 @@ function DrawerNavigator({
DrawerNavigationEventMap
>(DrawerRouter, {
initialRouteName,
defaultStatus:
defaultStatus !== undefined
? defaultStatus
: openByDefault
? 'open'
: 'closed',
defaultStatus,
backBehavior,
children,
screenListeners,
Expand All @@ -118,6 +121,7 @@ function DrawerNavigator({
<NavigationContent>
<DrawerView
{...rest}
defaultStatus={defaultStatus}
state={state}
descriptors={descriptors}
navigation={navigation}
Expand Down
3 changes: 2 additions & 1 deletion packages/drawer/src/utils/DrawerStatusContext.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { DrawerStatus } from '@react-navigation/native';
import * as React from 'react';

const DrawerStatusContext =
React.createContext<'open' | 'closed' | undefined>(undefined);
React.createContext<DrawerStatus | undefined>(undefined);

export default DrawerStatusContext;
7 changes: 4 additions & 3 deletions packages/drawer/src/utils/getDrawerStatusFromState.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import type {
DrawerNavigationState,
DrawerStatus,
ParamListBase,
} from '@react-navigation/native';

export default function getDrawerStatusFromState(
state: DrawerNavigationState<ParamListBase>
) {
): DrawerStatus {
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?"
);
}

const entry = state.history.find((it) => it.type === 'drawer') as
| { type: 'drawer'; status: 'open' }
| { type: 'drawer'; status: DrawerStatus }
| undefined;

return entry?.status ?? 'closed';
return entry?.status ?? state.default ?? 'closed';
}
26 changes: 20 additions & 6 deletions packages/drawer/src/views/DrawerView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
import {
DrawerActions,
DrawerNavigationState,
DrawerStatus,
ParamListBase,
useTheme,
} from '@react-navigation/native';
Expand Down Expand Up @@ -39,6 +40,7 @@ import { GestureHandlerRootView } from './GestureHandler';
import { MaybeScreen, MaybeScreenContainer } from './ScreenFallback';

type Props = DrawerNavigationConfig & {
defaultStatus: DrawerStatus;
state: DrawerNavigationState<ParamListBase>;
navigation: DrawerNavigationHelpers;
descriptors: DrawerDescriptorMap;
Expand Down Expand Up @@ -71,6 +73,7 @@ function DrawerViewBase({
state,
navigation,
descriptors,
defaultStatus,
drawerContent = (props: DrawerContentComponentProps) => (
<DrawerContent {...props} />
),
Expand Down Expand Up @@ -132,25 +135,29 @@ function DrawerViewBase({
}, [navigation, state.key]);

React.useEffect(() => {
if (drawerStatus !== 'open' || drawerType === 'permanent') {
if (drawerStatus === defaultStatus || drawerType === 'permanent') {
return;
}

const handleClose = () => {
const handleHardwareBack = () => {
// We shouldn't handle the back button if the parent screen isn't focused
// This will avoid the drawer overriding event listeners from a focused screen
if (!navigation.isFocused()) {
return false;
}

handleDrawerClose();
if (defaultStatus === 'open') {
handleDrawerOpen();
} else {
handleDrawerClose();
}

return true;
};

const handleEscape = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
handleClose();
handleHardwareBack();
}
};

Expand All @@ -159,7 +166,7 @@ function DrawerViewBase({
// This will make sure that our handler will run first when back button is pressed
const subscription = BackHandler.addEventListener(
'hardwareBackPress',
handleClose
handleHardwareBack
);

if (Platform.OS === 'web') {
Expand All @@ -173,7 +180,14 @@ function DrawerViewBase({
document?.body?.removeEventListener?.('keyup', handleEscape);
}
};
}, [drawerStatus, drawerType, handleDrawerClose, navigation]);
}, [
defaultStatus,
drawerStatus,
drawerType,
handleDrawerClose,
handleDrawerOpen,
navigation,
]);

const renderDrawerContent = () => {
return (
Expand Down

0 comments on commit de2d4e4

Please sign in to comment.