React navigation box status? (open or closed)
DrawerClose
Custom navigation actions are required to capture the event :
const MyDrawerNavigator = DrawerNavigator({
//...
});
const defaultGetStateForAction = MyDrawerNavigator.router.getStateForAction;
MyDrawerNavigator.router.getStateForAction = (action, state) => {
//use 'DrawerOpen' to capture drawer open event
if (state && action.type === 'Navigation/NAVIGATE' && action.routeName === 'DrawerClose') {
console.log('DrawerClose');
//write the code you want to deal with 'DrawerClose' event
}
return defaultGetStateForAction(action, state);
};
source to share
According to @ufxmeng
import {
StatusBar,
} from "react-native";
const MyDrawerNavigator = DrawerNavigator({
//...
});
const defaultGetStateForAction = MyDrawerNavigator.router.getStateForAction;
MyDrawerNavigator.router.getStateForAction = (action, state) => {
if(state && action.type === 'Navigation/NAVIGATE' && action.routeName === 'DrawerClose') {
StatusBar.setHidden(false);
}
if(state && action.type === 'Navigation/NAVIGATE' && action.routeName === 'DrawerOpen') {
StatusBar.setHidden(true);
}
return defaultGetStateForAction(action, state);
};
See here https://github.com/react-community/react-navigation/blob/673b9d2877d7e84fbfbe2928305ead7e51b04835/docs/api/routers/Routers.md and here https://github.com/aksonov/react-native-router-fx / questions / 699
source to share
This is for those using react-navigation v2. 0+. Now you can track actions with mailboxes.
{
OPEN_DRAWER: 'Navigation/OPEN_DRAWER',
CLOSE_DRAWER: 'Navigation/CLOSE_DRAWER',
TOGGLE_DRAWER: 'Navigation/TOGGLE_DRAWER',
DRAWER_OPENED: 'Navigation/DRAWER_OPENED',
DRAWER_CLOSED: 'Navigation/DRAWER_CLOSED'
}
response-navigation.js line 825
However, it seems that the implied navigation through the drawers from, say, swiping doesn't trigger the OPEN_
/ actions CLOSE_
, since you didn't manually switch it. However, actions _OPENED
/ _CLOSED
fires later.
const MyDrawerNavigator = createDrawerNavigator(...);
const defaultGetStateForAction = MyDrawerNavigator.router.getStateForAction;
MyDrawerNavigator.router.getStateForAction = (action, state) => {
switch (action.type) {
case 'Navigation/OPEN_DRAWER':
case 'Navigation/DRAWER_OPENED':
StatusBar.setHidden(true, 'slide');
break;
case 'Navigation/CLOSE_DRAWER':
case 'Navigation/DRAWER_CLOSED':
StatusBar.setHidden(false, 'slide');
break;
}
return defaultGetStateForAction(action, state);
};
source to share
Working with "navigation reaction": "^ 3.5.1"
const defaultGetStateForAction = DrawerNav.router.getStateForAction;
DrawerNav.router.getStateForAction = (action, state) => {
if(action){
if(action.type == 'Navigation/MARK_DRAWER_SETTLING' && action.willShow){
StatusBar.setHidden(true);
} else if(action.type == 'Navigation/MARK_DRAWER_SETTLING' && !action.willShow) {
StatusBar.setHidden(false);
}
}
return defaultGetStateForAction(action, state);
};
source to share
I found something similar to asdfghjklm
.
Here is my code that works fine even when you use to open and then use a button to close it:
openCloseDrawer = (props) => {
if (props.navigation.state.index == 1) {
props.navigation.navigate('DrawerClose');
} else {
props.navigation.navigate('DrawerOpen');
}
}
I execute this function when the user clicks the Open / Close Drawer button.
source to share
Based on the solution by Brad Boombalow, Fredrivette (thank you, man), I find a faster solution to the answer (the other solution is delaying seconds in some cases).
const defaultGetStateForAction = StackLogadoDrawer.router.getStateForAction;
StackLogadoDrawer.router.getStateForAction = (action, state) => {
switch (action.type) {
case 'Navigation/MARK_DRAWER_SETTLING':
if (action.willShow == false) {
console.log('CERRADO');
} else if (action.willShow == true) {
console.log('ABIERTO');
}
break;
}
return defaultGetStateForAction(action, state);
};
It only fires when there is an action (or very close).
Works on gestures or openDrawer () call
Anyway, I think this is a "must have" simple and straightforward way in the API
source to share
Hmm, not really much. One way would be to control the opening / closing of the drawer manually using:
this.props.navigation.navigate('DrawerOpen'); // open drawer
this.props.navigation.navigate('DrawerClose'); // close drawer
This way you can close your private / public events in a function where you can do whatever you want before opening / closing.
The only other possible solution I've seen in my docs is using a custom contentComponent
. You can pass a function to an event onItemPress(route)
, so maybe you can try connecting to it.
source to share
This works fine in React-Native, not sure about React .
In my case, I had to change the StatusBar , so I didn't need to know if the box is completely closed or not, so the code below worked for me ...
props.navigation.state.drawerMovementDirection === 'closing'
? //it is closing not fully closed
: (props.navigation.state.drawerMovementDirection === 'opening' ||
props.navigation.state.isDrawerOpen) && (
//fully opened or opening
)
If you don't need immediate information, you can use the code below and it will work fine and give you an exact answer whether the box is open or not!
Note. The answer will be delayed, in my case it took 1 second.
props.navigation.state.isDrawerOpen?
//open
:
//close;
If the solution doesn't work, I'm really sorry, but first of all, the answer won't work! So this is the version that works for me :))
source to share
For those who want to wire it up so that the drawer events are available on one of your screens or components instead of the top level app, I was able to wire it up using screenProps as described in this post . First, you set up screenProps in your application and pass the router and whatever you need. You can extract the screenProps from the props and use it as a screen or component (in this example I wired it in the constructor) by using getStateForAction to set setState in your router event driven component.
Here's an example (some code has been removed for clarity)
App.js
import React from 'react';
import { AppLoading } from 'expo';
import {
createDrawerNavigator,
createAppContainer,
createStackNavigator,
} from 'react-navigation';
import { HomeScreen } from './src/screens/HomeScreen.android';
import { LanguageSelectScreen } from './src/screens/LanguageSelectScreen';
export default class App extends React.Component {
state = {
isLoadingComplete: false,
isTilted: false,
};
constructor() {
super();
}
render() {
if (!this.state.isLoadingComplete && !this.props.skipLoadingScreen) {
return (
<AppLoading />
);
} else {
return (
<MyApp screenProps={MyAppNavigator.router} />
);
}
}
}
const MyAppNavigator = createDrawerNavigator(
{
Home: {
screen: HomeScreen,
},
PlayerNameScreen: {
screen: PlayerNameScreen,
},
},
{
unmountInactiveRoutes: true,
initialRouteName: 'PlayerNameScreen',
},
);
const RootStack = createStackNavigator(
{
Main: {
screen: MyAppNavigator,
},
MyModal: {
screen: LanguageSelectScreen,
},
},
{
mode: 'modal',
headerMode: 'none',
},
);
export const MyApp = createAppContainer(RootStack);
HomeScreen.android.js
import React from 'react';
import {Icon} from 'react-native-elements';
export class HomeScreen extends React.Component {
static navigationOptions = {
drawerLabel: () => 'Home',
drawerIcon: ({ tintColor }) => (
<Icon
name="checkerboard"
type="material-community"
size={25}
color={tintColor}
/>
),
};
constructor(props) {
super(props);
const router = props.screenProps;
const defaultGetStateForAction = router.getStateForAction;
router.getStateForAction = (action, state) => {
switch (action.type) {
case 'Navigation/MARK_DRAWER_SETTLING':
if (action.willShow == false) {
console.log('CLOSED');
this.setState({ isTilted: false });
} else if (action.willShow == true) {
this.setState({ isTilted: true });
console.log('OPEN');
}
break;
}
return defaultGetStateForAction(action, state);
};
this.state = {
isTilted: false,
};
}
render() {
const { isTilted } = this.state;
// ... render using isTilted
}
}
source to share
Without Redux integration, you can use onNavigationStateChange for the router component. Just intercept the drawer actions: DrawerOpen and DrawerClose .
Example:
handleNavigationState = (previous, next, action) => {
if (action.routeName === 'DrawerOpen') {
this.props.setDrawerState(true);
} else if (action.routeName === 'DrawerClose') {
this.props.setDrawerState(false);
}
}
render() {
return (
<Router onNavigationStateChange={this.handleNavigationState} />
);
}
source to share
I know this is late, but for anyone looking for an answer:
Box opening / closing logic:
this.props.navigation.state.routes[0].index
It is 0 for closed, 1 for open.
You can also switch boxes with
this.props.navigation.navigate('DrawerToggle')
instead
this.props.navigation.navigate('DrawerOpen');
or
this.props.navigation.navigate('DrawerClose');
It seems to me that this is more convenient for me and I haven't had any problems yet. Although it's nice to know that they are toggling or not to trigger other actions.
I truly believe that React-Navigation has one of the worst docs I have ever seen. There are teams that nobody knows about. I couldn't find the DrawerToggle action in the docs and I only did it using console.log (this.props.navigation);
source to share