React navigation box status? (open or closed)

I am creating a box with React Navigation and want to execute some logic if the user closes the box. I don't see anything obvious in the documentation that will allow me to do this. Does anyone know how to do this?

+6


source to share


11 replies


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);
};

      

+11


source


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

+6


source


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);
};
      

Run code


+5


source


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);
};


      

+2


source


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.

+1


source


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

+1


source


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.

0


source


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 :))

0


source


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
  }

}

      

0


source


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} />
    );
  }

      

-1


source


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);

-1


source







All Articles