Reputation: 3086
It was previously possible to open a specific drawer from a button, using getCustomActionCreators
, prior to v5 of React Navigation.
An example of doing that is here: React Native two drawers on one screen
However, it looks like this function has been removed. Is there a way to do this in React Navigation 5?
Upvotes: 0
Views: 1053
Reputation: 3086
This is possible by creating a custom router.
Here are a few key pieces of insight:
These notes have been verified against the following versions:
Custom action:
export const openSecondDrawerAction = { type: 'OPEN_SECOND_DRAWER' };
Helper function to dispatch custom action (optional)
export const openSecondDrawer = navigation => {
navigation.dispatch(openSecondDrawerAction);
};
Custom router
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);
}
}
};
};
Custom navigator
This is based on the code from 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)();
};
Create navigator instance(s) Now we can control two drawers, where the first is handled as a standard drawer, and the second uses the modified router:
const FirstDrawer = createDrawerNavigator()
const SecondDrawer = createDrawerNavigatorWithRouter(SecondDrawerRouter)
Nesting your navigators It is necessary to nest the navigators as follows:
<FirstDrawer.Navigator>
// then wrap the required FirstDrawer.Screen entry/ies with:
<SecondDrawer.Navigator>
</SecondDrawer.Navigator>
</FirstDrawer.Navigator>
This is a conceptual view, as its unfortunately not as simple as this to define nested navigators - you need to define Screen components which are themselves wrapped in the second navigator
Repeat
It should be possible to duplicate the above (with different action names) for a third or more drawers. createDrawerNavigatorWithRouter
can be reused without duplication, as it's generic to drawer navigators.
Upvotes: 1