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.
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
If you would like to determine if drawer is open or closed, you can do the following: import { useDrawerStatus } from '@react-navigation/drawer'; // ...
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.
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.
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.
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
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.
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
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:
And then after I close the drawer, the new warning appears like this:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With