Status of React Navigation drawer? (open or closed

2020-03-01 19:53发布

I'm building a drawer with React Navigation and want to perform some logic if the user closes the drawer. I don't see anything obvious in the documentation that will allow me to do this. Is anyone aware of a way to do this?

11条回答
再贱就再见
2楼-- · 2020-03-01 20:31

This is working fine in React-Native, not sure about React.

For my case I had to change the StatusBar so I did not need know wether the Drawer is closed fully or not, So below code 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 to know immediate then you can use below code, and this will work fine and will give you accurate answer whether the Drawer is Open or Not!

Note: This will be delayed answer, in my case it was taking 1 sec.

        props.navigation.state.isDrawerOpen?
                //open
                :
                //close;

If the solution does't work I am very sorry, but above all answer did not worked! So this is the version which is working for me:))

查看更多
爱情/是我丢掉的垃圾
3楼-- · 2020-03-01 20:35

You need to custom navigation actions to capture the DrawerClose 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);
};
查看更多
一夜七次
4楼-- · 2020-03-01 20:35

Based on Brad Bumbalough, fredrivett (thank you mans) solution I find a more fast response solution (the other solution delays secons in some uses).

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

This is fired just immediately actions occurs (or very near).

It works on gestures or calling openDrawer()

Anyway I think this is a "must have" easy and direct way in the API

查看更多
The star\"
5楼-- · 2020-03-01 20:35

For anyone looking to wire it up such that the drawer events are available in one of your Screens or Components instead of the top level app, I was able to wire that up by using screenProps as described in this post. You first set up the screenProps on your app and pass in the router and whatever else you need. You can pull screenProps off the props and use it your screen or component (I wired it up in the constructor in this example), use getStateForAction to setState in your component driven off the router events.

Here is an example (some code 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
  }

}
查看更多
Fickle 薄情
6楼-- · 2020-03-01 20:42

Without Redux integration can be used onNavigationStateChange on router component. Just intercept 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} />
    );
  }
查看更多
干净又极端
7楼-- · 2020-03-01 20:42

I know this is late, but for anyone who is looking for an answer:

The logic for the drawer being open/closed is in:

this.props.navigation.state.routes[0].index

It's 0 for closed, 1 for open.

You can also toggle the Drawers with

this.props.navigation.navigate('DrawerToggle')

instead of

this.props.navigation.navigate('DrawerOpen'); or

this.props.navigation.navigate('DrawerClose');

It seems to be more convenient for me and I have not happened upon any problems yet. Although it's nice to know whether they are toggled or not in order to invoke other actions.

I truly believe React-Navigation has one of the worst documentation that I have ever seen. There are commands that nobody knows about. I could not find the DrawerToggle action in the documents, and I only happened upon it through using console.log(this.props.navigation);

查看更多
登录 后发表回答