在 React Navigation 5 中从按钮打开两个抽屉之一

Open one of two drawers from button in react navigation 5

在 React Navigation v5 之前,以前可以使用 getCustomActionCreators 从按钮打开特定的抽屉。

这里有一个这样做的例子:

不过,这个功能好像已经被移除了。有没有办法在 React Navigation 5 中做到这一点?

这可以通过创建自定义路由器来实现。

以下是一些重要的见解:

  • 导航器冒出他们不处理的操作。这意味着我们需要为每个抽屉创建自定义操作。
  • 为了创建自定义操作,我们需要创建自定义路由器。
  • 为了使用自定义路由器,我们需要构建一个新的导航器。

这些注释已针对以下版本进行了验证:

  • @react-navigation/native: 5.8.0
  • @react-navigation/drawer: 5.10.0
  • @react-navigation/routers: 5.5.0

自定义操作:

export const openSecondDrawerAction = { type: 'OPEN_SECOND_DRAWER' };

调度自定义操作的辅助函数(可选)

export const openSecondDrawer = navigation => {
    navigation.dispatch(openSecondDrawerAction);
};

自定义路由器

import { DrawerRouter } '@react-navigation/routers';

const SecondDrawerRouter = options => {
  const router = DrawerRouter(options);
  return {
    ...router,
    getStateForAction: (state, action, options) => {
      switch (action.type) {
        case 'OPEN_SECOND_DRAWER':
          // CATCH THIS ACTION BUT MODIFY TO AN OPEN_DRAWER
          return router.getStateForAction(state, {
            ...action,
            type: 'OPEN_DRAWER'
          }, options);
        case 'OPEN_DRAWER':
          // DO NOT HANDLE THIS ACTION, LET IT BUBBLE TO THE PRIMARY DRAWER
          return null;
        default:
          return router.getStateForAction(state, action, options);
      }
    }
  };
};

自定义导航器

这基于 createDrawerNavigator 中的代码。

import { useNavigationBuilder, createNavigatorFactory } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { DrawerView, DrawerActions } from '@react-navigation/drawer';

const createDrawerNavigatorWithRouter = router => {
  function DrawerNavigator({ initialRouteName, openByDefault, backBehavior, children, screenOptions, ...rest }) {
    const { state, descriptors, navigation } = useNavigationBuilder(router, {
      initialRouteName,
      openByDefault,
      backBehavior,
      children,
      screenOptions
    });
    return <DrawerView {...rest} state={state} descriptors={descriptors} navigation={navigation} />;
  }
  return createNavigatorFactory(DrawerNavigator)();
};

创建导航器实例 现在我们可以控制两个抽屉,其中第一个作为标准抽屉处理,第二个使用修改后的路由器:

const FirstDrawer = createDrawerNavigator()
const SecondDrawer = createDrawerNavigatorWithRouter(SecondDrawerRouter)

嵌套导航器 需要嵌套导航器如下:

<FirstDrawer.Navigator>
    // then wrap the required FirstDrawer.Screen entry/ies with:
    <SecondDrawer.Navigator>
    </SecondDrawer.Navigator>
</FirstDrawer.Navigator>

这是一个概念视图,不幸的是,定义嵌套导航器并不像这样简单 - 您需要定义屏幕组件,这些组件本身包含在第二个导航器中

重复 应该可以为第三个或更多抽屉复制上述内容(使用不同的操作名称)。 createDrawerNavigatorWithRouter 可以重复使用而无需重复,因为它对抽屉导航器是通用的。