diff --git a/packages/drawer/src/navigators/createDrawerNavigator.tsx b/packages/drawer/src/navigators/createDrawerNavigator.tsx index 1bd53a0e..a0de4203 100644 --- a/packages/drawer/src/navigators/createDrawerNavigator.tsx +++ b/packages/drawer/src/navigators/createDrawerNavigator.tsx @@ -19,7 +19,7 @@ import { type Props = DefaultNavigatorOptions & DrawerRouterOptions & - Partial; + DrawerNavigationConfig; function DrawerNavigator({ initialRouteName, diff --git a/packages/drawer/src/types.tsx b/packages/drawer/src/types.tsx index 27be1afc..47fbb0ff 100644 --- a/packages/drawer/src/types.tsx +++ b/packages/drawer/src/types.tsx @@ -20,14 +20,14 @@ export type DrawerNavigationConfig = { /** * Position of the drawer on the screen. Defaults to `left`. */ - drawerPosition: 'left' | 'right'; + drawerPosition?: 'left' | 'right'; /** * Type of the drawer. It determines how the drawer looks and animates. * - `front`: Traditional drawer which covers the screen with a overlay behind it. * - `back`: The drawer is revealed behind the screen on swipe. * - `slide`: Both the screen and the drawer slide on swipe to reveal the drawer. */ - drawerType: 'front' | 'back' | 'slide'; + drawerType?: 'front' | 'back' | 'slide'; /** * How far from the edge of the screen the swipe gesture should activate. */ @@ -35,12 +35,12 @@ export type DrawerNavigationConfig = { /** * Whether the statusbar should be hidden when the drawer is pulled or opens, */ - hideStatusBar: boolean; + hideStatusBar?: boolean; /** * Whether the keyboard should be dismissed when the swipe gesture begins. * Defaults to `'on-drag'`. Set to `'none'` to disable keyboard handling. */ - keyboardDismissMode: 'on-drag' | 'none'; + keyboardDismissMode?: 'on-drag' | 'none'; /** * Minimum swipe distance threshold that should activate opening the drawer. */ @@ -53,7 +53,7 @@ export type DrawerNavigationConfig = { /** * Animation of the statusbar when hiding it. use in combination with `hideStatusBar`. */ - statusBarAnimation: 'slide' | 'none' | 'fade'; + statusBarAnimation?: 'slide' | 'none' | 'fade'; /** * Props to pass to the underlying pan gesture handler. */ @@ -62,7 +62,7 @@ export type DrawerNavigationConfig = { * Whether the screens should render the first time they are accessed. Defaults to `true`. * Set it to `false` if you want to render all screens on initial render. */ - lazy: boolean; + lazy?: boolean; /** * Whether a screen should be unmounted when navigating away from it. * Defaults to `false`. @@ -72,7 +72,7 @@ export type DrawerNavigationConfig = { * Function that returns React element to render as the content of the drawer, for example, navigation items. * Defaults to `DrawerContent`. */ - drawerContent: (props: DrawerContentComponentProps) => React.ReactNode; + drawerContent?: (props: DrawerContentComponentProps) => React.ReactNode; /** * Options for the content component which will be passed as props. */ diff --git a/packages/drawer/src/views/DrawerContentScrollView.tsx b/packages/drawer/src/views/DrawerContentScrollView.tsx index 9a702b62..df2d7a57 100644 --- a/packages/drawer/src/views/DrawerContentScrollView.tsx +++ b/packages/drawer/src/views/DrawerContentScrollView.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { ScrollView, StyleSheet, ScrollViewProps } from 'react-native'; import { useSafeArea } from 'react-native-safe-area-context'; -import { useTheme } from '@react-navigation/native'; type Props = ScrollViewProps & { drawerPosition: 'left' | 'right'; @@ -16,7 +15,6 @@ export default function DrawerContentScrollView({ ...rest }: Props) { const insets = useSafeArea(); - const { colors } = useTheme(); return ( {children} diff --git a/packages/drawer/src/views/DrawerView.tsx b/packages/drawer/src/views/DrawerView.tsx index 4d233e4b..2f637708 100644 --- a/packages/drawer/src/views/DrawerView.tsx +++ b/packages/drawer/src/views/DrawerView.tsx @@ -13,6 +13,7 @@ import { DrawerNavigationState, DrawerActions, } from '@react-navigation/routers'; +import { useTheme } from '@react-navigation/native'; import DrawerGestureContext from '../utils/DrawerGestureContext'; import SafeAreaProviderCompat from './SafeAreaProviderCompat'; @@ -26,16 +27,10 @@ import { DrawerContentComponentProps, } from '../types'; -type Props = Omit & { +type Props = DrawerNavigationConfig & { state: DrawerNavigationState; navigation: DrawerNavigationHelpers; descriptors: DrawerDescriptorMap; - overlayColor: string; -}; - -type State = { - loaded: number[]; - drawerWidth: number; }; const getDefaultDrawerWidth = ({ @@ -62,49 +57,52 @@ const getDefaultDrawerWidth = ({ /** * Component that renders the drawer. */ -export default class DrawerView extends React.PureComponent { - static defaultProps = { - lazy: true, - drawerContent: (props: DrawerContentComponentProps) => ( - - ), - drawerPosition: I18nManager.isRTL ? 'right' : 'left', - keyboardDismissMode: 'on-drag', - overlayColor: 'rgba(0, 0, 0, 0.5)', - drawerType: 'front', - hideStatusBar: false, - statusBarAnimation: 'slide', - }; +export default function DrawerView({ + state, + navigation, + descriptors, + lazy = true, + drawerContent = (props: DrawerContentComponentProps) => ( + + ), + drawerPosition = I18nManager.isRTL ? 'right' : 'left', + keyboardDismissMode = 'on-drag', + overlayColor = 'rgba(0, 0, 0, 0.5)', + drawerType = 'front', + hideStatusBar = false, + statusBarAnimation = 'slide', + drawerContentOptions, + drawerStyle, + edgeWidth, + gestureHandlerProps, + minSwipeDistance, + sceneContainerStyle, + unmountInactiveScreens, +}: Props) { + const [loaded, setLoaded] = React.useState([state.index]); + const [drawerWidth, setDrawerWidth] = React.useState(() => + getDefaultDrawerWidth(Dimensions.get('window')) + ); - static getDerivedStateFromProps(nextProps: Props, prevState: State) { - const { index } = nextProps.state; + const drawerGestureRef = React.useRef(null); - return { - // Set the current tab to be loaded if it was not loaded before - loaded: prevState.loaded.includes(index) - ? prevState.loaded - : [...prevState.loaded, index], + const { colors } = useTheme(); + + React.useEffect(() => { + const updateWidth = ({ window }: { window: ScaledSize }) => { + setDrawerWidth(getDefaultDrawerWidth(window)); }; + + Dimensions.addEventListener('change', updateWidth); + + return () => Dimensions.removeEventListener('change', updateWidth); + }, []); + + if (!loaded.includes(state.index)) { + setLoaded([...loaded, state.index]); } - state: State = { - loaded: [this.props.state.index], - drawerWidth: getDefaultDrawerWidth(Dimensions.get('window')), - }; - - componentDidMount() { - Dimensions.addEventListener('change', this.updateWidth); - } - - componentWillUnmount() { - Dimensions.removeEventListener('change', this.updateWidth); - } - - private drawerGestureRef = React.createRef(); - - private handleDrawerOpen = () => { - const { state, navigation } = this.props; - + const handleDrawerOpen = () => { navigation.dispatch({ ...DrawerActions.openDrawer(), target: state.key, @@ -113,9 +111,7 @@ export default class DrawerView extends React.PureComponent { navigation.emit({ type: 'drawerOpen' }); }; - private handleDrawerClose = () => { - const { state, navigation } = this.props; - + const handleDrawerClose = () => { navigation.dispatch({ ...DrawerActions.closeDrawer(), target: state.key, @@ -124,24 +120,7 @@ export default class DrawerView extends React.PureComponent { navigation.emit({ type: 'drawerClose' }); }; - private updateWidth = ({ window }: { window: ScaledSize }) => { - const drawerWidth = getDefaultDrawerWidth(window); - - if (this.state.drawerWidth !== drawerWidth) { - this.setState({ drawerWidth }); - } - }; - - private renderNavigationView = ({ progress }: any) => { - const { - state, - navigation, - descriptors, - drawerPosition, - drawerContent, - drawerContentOptions, - } = this.props; - + const renderNavigationView = ({ progress }: any) => { return drawerContent({ ...drawerContentOptions, progress: progress, @@ -152,11 +131,7 @@ export default class DrawerView extends React.PureComponent { }); }; - private renderContent = () => { - let { lazy, state, descriptors, unmountInactiveScreens } = this.props; - - const { loaded } = this.state; - + const renderContent = () => { return ( {state.routes.map((route, index) => { @@ -164,7 +139,7 @@ export default class DrawerView extends React.PureComponent { return null; } - if (lazy && !loaded.includes(index)) { + if (lazy && !loaded.includes(index) && index !== state.index) { // Don't render a screen if we've never navigated to it return null; } @@ -186,58 +161,45 @@ export default class DrawerView extends React.PureComponent { ); }; - private setDrawerGestureRef = (ref: PanGestureHandler | null) => { - // @ts-ignore - this.drawerGestureRef.current = ref; - }; + const activeKey = state.routes[state.index].key; + const { gestureEnabled } = descriptors[activeKey].options; - render() { - const { - state, - descriptors, - drawerType, - drawerPosition, - overlayColor, - sceneContainerStyle, - drawerStyle, - edgeWidth, - minSwipeDistance, - hideStatusBar, - statusBarAnimation, - gestureHandlerProps, - } = this.props; - - const { drawerWidth } = this.state; - - const activeKey = state.routes[state.index].key; - const { gestureEnabled } = descriptors[activeKey].options; - - return ( - - - - - - ); - } + return ( + + + { + // @ts-ignore + drawerGestureRef.current = ref; + }} + gestureHandlerProps={gestureHandlerProps} + drawerType={drawerType} + drawerPosition={drawerPosition} + sceneContainerStyle={[ + { backgroundColor: colors.background }, + sceneContainerStyle, + ]} + drawerStyle={[ + { width: drawerWidth, backgroundColor: colors.card }, + drawerStyle, + ]} + overlayStyle={{ backgroundColor: overlayColor }} + swipeEdgeWidth={edgeWidth} + swipeDistanceThreshold={minSwipeDistance} + hideStatusBar={hideStatusBar} + statusBarAnimation={statusBarAnimation} + renderDrawerContent={renderNavigationView} + renderSceneContent={renderContent} + keyboardDismissMode={keyboardDismissMode} + drawerPostion={drawerPosition} + /> + + + ); } const styles = StyleSheet.create({