Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect when the drawer is opened in react-navigation?

I'm using react-navigation's DrawerNavigator in my app. I would like to detect when a user drags open the side menu so that i can perform a certain action, e.g dismiss an opened Keyboard. How can i do this? i can't seem to find a solution in the docs. Thank you.

Here is my code

import React from 'react';
import { Dimensions } from 'react-native';
import { Icon } from 'react-native-elements';
import { DrawerNavigator, StackNavigator, addNavigationHelpers } from 'react-navigation';


//redux related imports
import { createStore, combineReducers } from 'redux';
import { Provider, connect } from 'react-redux';

import Attendance from './containers/pages/Attendance';
import Fees from './containers/pages/Fees';
import Exams from './containers/pages/Exams';
import InitializeUser from './containers/pages/InitializeUser';
import Landing from './Landing';
import Login from './containers/pages/Login';
import Search from './containers/pages/Search';
import Staff from './containers/pages/Staff';
import Stats from './containers/pages/Stats';
import Students from './containers/pages/Students';
import Verification from './containers/pages/verify';
import ProfileDetail from './components/pages/ProfileDetail';
import FeesDetail from './containers/pages/FeesDetails';


import MainReport from './containers/pages/Reports/Main_Report';
import AcademicDetails from './containers/pages/Reports/Student_Academic_Details';
import { Constants } from './config';
import ResultsLanding from './containers/pages/Reports/ResultsLanding';
import { CustomDrawerContentComponent } from '../src/components/base/SideMenu';


const screenWidth = Dimensions.get('window').width;
const MainPages = DrawerNavigator({
  StudentsPage: {
    path: '/Students',
    screen: Students
  },
  SearchPage: {
    path: '/Seacrh',
    screen: Search
  },

  Staff: {
    path: '/Staff',
    screen: Staff
  },

  Fees: {
    path: '/Fees',
    screen: Fees
  },
  Stats: {
    path: '/Stats',
    screen: Stats
  },
  Results: {
    screen: ResultsLanding,
    navigationOptions: {
      tintColor: 'red',
      flex: 1,
      drawerIcon: ({ tintColor }) => (
        <Icon
          name="content-paste"
          color={tintColor}
        />
      )
    }
  },
  Attendance:
  {
    path: '/Attendance',
    screen: Attendance
  },
},
  {
    initialRouteName: 'StudentsPage',
    contentOptions: {
      activeTintColor: Constants.ui.THEME,
      activeBackgroundColor: 'rgba(0,0,0,0.1)',
      inactiveTintColor: 'rgba(0,0,0,0.6)',
      labelStyle: {
        fontSize: 12,
        marginLeft: 10,
      },
    },

    drawerWidth: screenWidth > 320 ? 300 : 250,
    contentComponent: CustomDrawerContentComponent

  });

export const Navigator = StackNavigator({
  LandingPage: {
    screen: Landing,
    navigationOptions: {
      header: null
    }
  },
  LoginPage: {
    screen: Login,
    navigationOptions: {
      header: null
    },
  },
  ProfileDetailPage: {
    screen: ProfileDetail,
    headerMode: 'screen',
    navigationOptions: {
      header: null
    }
  },
  FeesDetailPage:
  {
    screen: FeesDetail,
    navigationOptions: {
      header: null
    },
  },
  VerifyPage: {
    screen: Verification,
    navigationOptions: {
      header: null
    },
  },
  InitUserPage: {
    screen: InitializeUser,
    navigationOptions: {
      header: null
    },
  },
  MainPages: {
    screen: MainPages,
    navigationOptions: {
      header: null
    }
  },

  MainReportPage: {
    screen: MainReport,
    navigationOptions: {
      header: null
    }
  },
  ExamsMainPage: {
    screen: Exams,
    navigationOptions: {
      header: null
    }
  },
  AcademicDetailsPage: {
    screen: AcademicDetails,
    navigationOptions: {
      header: null
    }
  },

});  

const initialState = MainPages.router.getStateForAction(
  MainPages.router.getActionForPathAndParams('StudentsPage'));  

const navReducer = (state = initialState, action) => {
  const nextState = MainPages.router.getStateForAction(action, state);
  return nextState || state;
}; 

const appReducer = combineReducers({
  nav: navReducer
});

class App extends React.Component {
  componentWillReceiveProps(nextProps) {
    console.warn('nextProps: ', JSON.stringify(nextProps, null, 4));
  }
  render() {
    return (
      <MainPages 
        navigation={addNavigationHelpers({
        dispatch: this.props.dispatch,
        state: this.props.nav,
      })} />
    );
  }
}

const mapStateToProps = (state) => ({
  nav: state.nav
});

const AppWithNavigationState = connect(mapStateToProps)(App);

const store = createStore(appReducer);

class Root extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <AppWithNavigationState />
      </Provider>
    );
  }
}

enter image description here Here is a screenshot of the error i get when i run the code

like image 559
daniel doe Avatar asked Jul 15 '17 19:07

daniel doe


People also ask

How do I know if my drawers are open react navigation?

If you would like to determine if drawer is open or closed, you can do the following: import { useDrawerStatus } from '@react-navigation/drawer'; // ...

How do you navigate in drawer navigation?

To open and close drawer, navigate to 'DrawerOpen' and 'DrawerClose' respectively. If you would like to toggle the drawer you can navigate to 'DrawerToggle' , and this will choose which navigation is appropriate for you given the drawers current state.

How do I use the drawer navigator in React Native?

To use this navigator, ensure that you have @react-navigation/native and its dependencies (follow this guide), then install @react-navigation/drawer: To use this drawer navigator, import it from @react-navigation/drawer: For a complete usage guide please visit Drawer Navigation. The name of the route to render on first load of the navigator.

What is the use of navigation in react navigation?

We want to use React Navigation. navigation.openDrawer (): It is used to open the drawer. navigation.closeDrawer (): It is used to close the drawer. navigation.toggleDrawer (): It is used to toggle the drawer.

How to toggle the navigation drawer in Expo-CLI?

navigation.closeDrawer (): It is used to close the drawer. navigation.toggleDrawer (): It is used to toggle the drawer. Step 1: Open your terminal and install expo-cli by the following command. Step 2: Now create a project by the following command. Step 3: Now go into your project folder i.e. myapp

Which reanimated version does the drawer Navigator support?

The Drawer Navigator supports both Reanimated 1 and Reanimated 2. If you want to use Reanimated 2, make sure to configure it following the installation guide. To use this drawer navigator, import it from @react-navigation/drawer: For a complete usage guide please visit Drawer Navigation.


2 Answers

Simply, if you use react-navigation v5 -

import { useIsDrawerOpen } from '@react-navigation/drawer'

const isOpen: boolean = useIsDrawerOpen()

then you have to subscribe on "isOpen" flag by hook useEffect:

useEffect(() => {
    if (!isOpen) {
      // Your dismiss logic here 
    }
}, [isOpen])

Your custom Drawer can look like DrawerContent

Hope it helped

like image 66
wentris Avatar answered Oct 11 '22 09:10

wentris


I was able to detect the DrawerNavigator's open and close side menu actions by following the Redux Integration guide and modifying it to use a DrawerNavigator instead of StackNavigator. Here is what I have inside my index.ios.js file. Near the bottom within the App class I use componentWillReceiveProps which displays a warning every time the drawer opens or closes.

import React from 'react';
import {
  AppRegistry,
  Image,
  Text,
  View,
  ScrollView
} from 'react-native';
import {DrawerNavigator, DrawerItems, addNavigationHelpers } from 'react-navigation';
import { Provider, connect } from 'react-redux'
import { createStore, combineReducers } from 'redux'

class MyHomeScreen extends React.Component {
  static navigationOptions = {
    drawerLabel: 'Home',
    drawerIcon: ({ tintColor }) => (
      <Image
        source={require('./images/Groups.png')}
        style={{tintColor: tintColor, width: 26, height: 26}}/>
    ),
  };
  render() {
    return (
      <View>
        <Text>Home Screen</Text>
      </View>
    );
  }
}

class MyNotificationsScreen extends React.Component {
  static navigationOptions = {
    drawerLabel: 'Notifications',
    drawerIcon: ({ tintColor }) => (
      <Image
        source={require('./images/Events.png')}
        style={{tintColor: tintColor, width: 26, height: 26}}/>
    ),
  };
  render() {
    return (
      <View>
        <Text>Notifications Screen</Text>
      </View>
    );
  }
}

const NavDemo = DrawerNavigator({
  Home: { screen: MyHomeScreen },
  Notifications: { screen: MyNotificationsScreen }
}, {
  tabBarOptions: {
    activeTintColor: '#e91e63',
  },
  drawerWidth: 200,
  drawerPosition: 'left',
  contentComponent: props => <ScrollView><DrawerItems {...props} /></ScrollView>
});

const initialState = NavDemo.router.getStateForAction(NavDemo.router.getActionForPathAndParams('Home'));

const navReducer = (state = initialState, action) => {
  const nextState = NavDemo.router.getStateForAction(action, state);
  return nextState || state;
};

const appReducer = combineReducers({
  nav: navReducer
});

class App extends React.Component {
  componentWillReceiveProps(nextProps) {
    console.warn('nextProps: ' + JSON.stringify(nextProps, null, 4))
  }
  render() {
    return (
      <NavDemo navigation={addNavigationHelpers({
        dispatch: this.props.dispatch,
        state: this.props.nav,
      })} />
    );
  }
}

const mapStateToProps = (state) => ({
  nav: state.nav
});

const AppWithNavigationState = connect(mapStateToProps)(App);

const store = createStore(appReducer);

class Root extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <AppWithNavigationState />
      </Provider>
    );
  }
}

AppRegistry.registerComponent('NavDemo', () => Root);

When I open the drawer and expand the warning nextProps looks like this:

enter image description here

And then after I close the drawer, the new warning appears like this:

enter image description here

nextProps.nav is an object with two keys, routes and index. When the drawer opens, index becomes 1, and when it closes, index becomes 0.

Using that information, you can add an if statement to perform your necessary actions when the drawer opens.

like image 41
Pat Needham Avatar answered Oct 11 '22 08:10

Pat Needham