Skip to content

Commit de2d4e4

Browse files
committed
fix: properly handle history if drawer is open by default
1 parent 8e7ba69 commit de2d4e4

File tree

8 files changed

+155
-74
lines changed

8 files changed

+155
-74
lines changed

example/src/Screens/MasterDetail.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ export default function DrawerScreen({ navigation, ...rest }: Props) {
123123

124124
return (
125125
<Drawer.Navigator
126+
backBehavior="none"
126127
defaultStatus="open"
127128
drawerContent={(props) => <CustomDrawerContent {...props} />}
128129
screenOptions={{

packages/drawer/src/navigators/createDrawerNavigator.tsx

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
DrawerNavigationState,
66
DrawerRouter,
77
DrawerRouterOptions,
8+
DrawerStatus,
89
ParamListBase,
910
useNavigationBuilder,
1011
} from '@react-navigation/native';
@@ -29,7 +30,7 @@ type Props = DefaultNavigatorOptions<
2930

3031
function DrawerNavigator({
3132
initialRouteName,
32-
defaultStatus,
33+
defaultStatus: customDefaultStatus,
3334
backBehavior,
3435
children,
3536
screenListeners,
@@ -92,6 +93,13 @@ function DrawerNavigator({
9293
);
9394
}
9495

96+
const defaultStatus: DrawerStatus =
97+
customDefaultStatus !== undefined
98+
? customDefaultStatus
99+
: openByDefault
100+
? 'open'
101+
: 'closed';
102+
95103
const { state, descriptors, navigation, NavigationContent } =
96104
useNavigationBuilder<
97105
DrawerNavigationState<ParamListBase>,
@@ -101,12 +109,7 @@ function DrawerNavigator({
101109
DrawerNavigationEventMap
102110
>(DrawerRouter, {
103111
initialRouteName,
104-
defaultStatus:
105-
defaultStatus !== undefined
106-
? defaultStatus
107-
: openByDefault
108-
? 'open'
109-
: 'closed',
112+
defaultStatus,
110113
backBehavior,
111114
children,
112115
screenListeners,
@@ -118,6 +121,7 @@ function DrawerNavigator({
118121
<NavigationContent>
119122
<DrawerView
120123
{...rest}
124+
defaultStatus={defaultStatus}
121125
state={state}
122126
descriptors={descriptors}
123127
navigation={navigation}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import type { DrawerStatus } from '@react-navigation/native';
12
import * as React from 'react';
23

34
const DrawerStatusContext =
4-
React.createContext<'open' | 'closed' | undefined>(undefined);
5+
React.createContext<DrawerStatus | undefined>(undefined);
56

67
export default DrawerStatusContext;
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
import type {
22
DrawerNavigationState,
3+
DrawerStatus,
34
ParamListBase,
45
} from '@react-navigation/native';
56

67
export default function getDrawerStatusFromState(
78
state: DrawerNavigationState<ParamListBase>
8-
) {
9+
): DrawerStatus {
910
if (state.history == null) {
1011
throw new Error(
1112
"Couldn't find the drawer status in the state object. Is it a valid state object of drawer navigator?"
1213
);
1314
}
1415

1516
const entry = state.history.find((it) => it.type === 'drawer') as
16-
| { type: 'drawer'; status: 'open' }
17+
| { type: 'drawer'; status: DrawerStatus }
1718
| undefined;
1819

19-
return entry?.status ?? 'closed';
20+
return entry?.status ?? state.default ?? 'closed';
2021
}

packages/drawer/src/views/DrawerView.tsx

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
import {
88
DrawerActions,
99
DrawerNavigationState,
10+
DrawerStatus,
1011
ParamListBase,
1112
useTheme,
1213
} from '@react-navigation/native';
@@ -39,6 +40,7 @@ import { GestureHandlerRootView } from './GestureHandler';
3940
import { MaybeScreen, MaybeScreenContainer } from './ScreenFallback';
4041

4142
type Props = DrawerNavigationConfig & {
43+
defaultStatus: DrawerStatus;
4244
state: DrawerNavigationState<ParamListBase>;
4345
navigation: DrawerNavigationHelpers;
4446
descriptors: DrawerDescriptorMap;
@@ -71,6 +73,7 @@ function DrawerViewBase({
7173
state,
7274
navigation,
7375
descriptors,
76+
defaultStatus,
7477
drawerContent = (props: DrawerContentComponentProps) => (
7578
<DrawerContent {...props} />
7679
),
@@ -132,25 +135,29 @@ function DrawerViewBase({
132135
}, [navigation, state.key]);
133136

134137
React.useEffect(() => {
135-
if (drawerStatus !== 'open' || drawerType === 'permanent') {
138+
if (drawerStatus === defaultStatus || drawerType === 'permanent') {
136139
return;
137140
}
138141

139-
const handleClose = () => {
142+
const handleHardwareBack = () => {
140143
// We shouldn't handle the back button if the parent screen isn't focused
141144
// This will avoid the drawer overriding event listeners from a focused screen
142145
if (!navigation.isFocused()) {
143146
return false;
144147
}
145148

146-
handleDrawerClose();
149+
if (defaultStatus === 'open') {
150+
handleDrawerOpen();
151+
} else {
152+
handleDrawerClose();
153+
}
147154

148155
return true;
149156
};
150157

151158
const handleEscape = (e: KeyboardEvent) => {
152159
if (e.key === 'Escape') {
153-
handleClose();
160+
handleHardwareBack();
154161
}
155162
};
156163

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

165172
if (Platform.OS === 'web') {
@@ -173,7 +180,14 @@ function DrawerViewBase({
173180
document?.body?.removeEventListener?.('keyup', handleEscape);
174181
}
175182
};
176-
}, [drawerStatus, drawerType, handleDrawerClose, navigation]);
183+
}, [
184+
defaultStatus,
185+
drawerStatus,
186+
drawerType,
187+
handleDrawerClose,
188+
handleDrawerOpen,
189+
navigation,
190+
]);
177191

178192
const renderDrawerContent = () => {
179193
return (

0 commit comments

Comments
 (0)