React native drawer navigation with I18nManager.forceRTL isn't working - react-native

Been trying to implement #react-navigation/drawer with #react-navigation/native-stack and forcing the app to be RTL, using Expo.
App.tsx:
import { I18nManager } from 'react-native'
import { SafeAreaProvider } from 'react-native-safe-area-view'
import {useLoading} from '#hooks'
I18nManager.forceRTL(true)
I18nManager.allowRTL(true)
export default function App() {
const isLoadingComplete = useLoading()
if (!isLoadingComplete) {
return null
} else {
return (
<SafeAreaProvider style={{flex:1}}>
<Navigation />
<StatusBar style="dark" />
</SafeAreaProvider>
)
}
}
Navigation.tsx:
import { createNativeStackNavigator, NativeStackNavigationOptions } from '#react-navigation/native-stack'
import { createDrawerNavigator } from '#react-navigation/drawer'
import { NavigationContainer } from '#react-navigation/native'
const Stack = createNativeStackNavigator<RootStackParamList>()
const Drawer = createDrawerNavigator<RootDrawerParamList>()
function RootNavigator() {
return (
<Stack.Navigator screenOptions={{presentation: 'modal', headerShown: false}}>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Root" component={DrawerNavigator} />
<Stack.Screen name="Customer" component={CustomerScreen} />
</Stack.Navigator>
)
}
function DrawerNavigator() {
return (
<View style={styles.container}>
<Drawer.Navigator initialRouteName='Customers' screenOptions={{headerRight: Logout}}>
<Drawer.Screen name="Home" component={HomeScreen} options={{title: Lang.Navigation.Home}} />
<Drawer.Screen name="Customers" component={CustomersScreen} options={{title: Lang.Navigation.Customers}} />
</Drawer.Navigator>
</View>
)
}
export default function Navigation() {
return (
<NavigationContainer ref={navigationRef} linking={LinkingConfiguration}>
<RootNavigator />
</NavigationContainer>
)
}
Dependencies:
"#react-navigation/drawer": "^6.1.8",
"#react-navigation/native": "^6.0.6",
"#react-navigation/native-stack": "^6.2.5",
"expo": "~44.0.0",
"react": "17.0.1",
"react-native": "0.64.3",
"react-native-safe-area-view": "^1.1.1",
The result i'm getting when clicking on the menu built-in hamburger is that the screen does become grayish but the menu never pops in. Using inspect I found that there is a problem with the menu's "left" and "translateX" settings automatically given by the react navigation plugin.
Everything works well when removing the 'ForceRTL' part, but I need the app the be RTL.

instead of using the following code.
I18nManager.forceRTL(true)
I18nManager.allowRTL(true)
fix for this issue is to use direction:'rtl' in the style of Root level component. sample working code demo https://snack.expo.dev/PIIGNx70v
sample code
import * as React from 'react';
import { Button, View } from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button onPress={navigation.openDrawer} title="Open drawer" />
</View>
);
}
const Drawer = createDrawerNavigator();
export default function App() {
return (
<View style={{ flex: 1, direction: 'rtl' }}>
<NavigationContainer>
<Drawer.Navigator drawerPosition="right" initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
</Drawer.Navigator>
</NavigationContainer>
</View>
);
}

Related

How to create a Drawer navigation in react native

I am trying to create a Stack navigation, A Drawer navigation and a Bottom Tab navigation. My Stack navigation and Bottom Tab navigation is working fine, but Can't make the Drawer Navigation. Could you tell me what I am missing here? It seems to me Drawer navigation and Tab navigation has a conflict in my code...but can't find why ??? Please help.
My App.js
import 'react-native-gesture-handler';
import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createDrawerNavigator, DrawerContentScrollView,DrawerItemList,DrawerItem, } from '#react-navigation/drawer';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import HomeScreen from './src/screens/HomeScreen';
import FeedScreen from './src/screens/FeedScreen';
import Cards from './src/screens/CardScreen';
import ProfileScreen from './src/screens/ProfileScreen';
import Message from './src/screens/MessagesScreen';
function DetailsScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Details!</Text>
</View>
);
}
function SettingsScreen({ navigation }) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Settings screen</Text>
<Button
title="Go to Cards"
onPress={() => navigation.navigate('Cards')}
/>
</View>
);
}
const HomeStack = createNativeStackNavigator();
function HomeStackScreen() {
return (
<HomeStack.Navigator initialRouteName="Home">
<HomeStack.Screen name="Home" component={HomeScreen} />
<HomeStack.Screen name="FeedScreen" component={FeedScreen} />
<HomeStack.Screen name="Message" component={Message} />
</HomeStack.Navigator>
);
}
const SettingsStack = createNativeStackNavigator();
function SettingsStackScreen() {
return (
<SettingsStack.Navigator>
<SettingsStack.Screen name="Settings" component={SettingsScreen} />
<SettingsStack.Screen name="Cards" component={Cards} />
</SettingsStack.Navigator>
);
}
const ProfileStack = createNativeStackNavigator();
function ProfileStackScreen(){
return (
<ProfileStack.Navigator>
<ProfileStack.Screen name="Profile" component={ProfileScreen}/>
{/* <ProfileStack.Screen name="Cards" component={Cards}/> */}
</ProfileStack.Navigator>
)
}
const Drawer = createDrawerNavigator();
function MyDrawer() {
return (
<Drawer.Navigator screenOptions={{ drawerPosition: 'left' }}>
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Message" component={Message} />
</Drawer.Navigator>
);
}
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator screenOptions={{ headerShown: false }}>
<Tab.Screen name="Home" component={HomeStackScreen} />
<Tab.Screen name="Settings" component={SettingsStackScreen} />
<Tab.Screen name="Profile" component={ProfileStackScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
I Have found the solutions, I just entered tab navigation into drawer navigation and now it's working fine
import 'react-native-gesture-handler';
import Animated, {
useSharedValue,
withTiming,
useAnimatedStyle,
Easing,
} from 'react-native-reanimated';
import * as React from 'react';
import { Button, Text, View } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createDrawerNavigator, DrawerContentScrollView,
DrawerItemList,
DrawerItem, } from '#react-navigation/drawer';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import HomeScreen from './src/screens/HomeScreen';
import FeedScreen from './src/screens/FeedScreen';
import Cards from './src/screens/CardScreen';
import ProfileScreen from './src/screens/ProfileScreen';
import Message from './src/screens/MessagesScreen';
const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
const Drawer = createDrawerNavigator();
function Tabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} options={{ headerShown: false }} />
<Tab.Screen name="Profile" component={ProfileScreen} options={{ headerShown: false }} />
<Tab.Screen name="Message" component={Message} options={{ headerShown: false }} />
</Tab.Navigator>
);
}
function StackNavigator() {
return (
<Stack.Navigator>
<Stack.Screen name="HomeScreen" component={HomeScreen} options={{ headerShown: false }} />
<Stack.Screen name="Message" component={Message} />
</Stack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Stack">
<Drawer.Screen name="Tabs" component={Tabs} />
</Drawer.Navigator>
</NavigationContainer>
);
}

React-native bottom navigation with stacknavigator

I'm new to React Native and trying to learn. but I couldn't do what I wanted to do.
I have Tab Navigations and I want to Open Stack when I click the button. But I can't figure out how to do it, thanks in advance for your help.
Snack
import * as React from 'react';
import { View,Text,TouchableOpacity,Button } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const Tab = createBottomTabNavigator();
const Stack = createNativeStackNavigator();
function Home() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Page</Text>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('FeedScreen')}
/>
</View>
);
}
function FeedScreen() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={Details} />
</Stack.Navigator>
);
}
function Details() {
return <View><Text>Details</Text></View>;
}
function Profile() {
return <View>
<Text>Profile</Text>
</View>;
}
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="Profile" component={Profile} />
</Tab.Navigator>
</NavigationContainer>
);
}
Your tabs can take a StackNavigator as the component and by default it will go to the first screen in that stack when you press the tab.
edit to your code
import * as React from 'react';
import { View,Text,TouchableOpacity,Button } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const Tab = createBottomTabNavigator();
const Stack = createNativeStackNavigator();
function Home() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Page</Text>
<Button
title="Go to Settings"
onPress={() => navigation.navigate('FeedScreen')}
/>
</View>
);
}
function Details() {
return <View><Text>Details</Text></View>;
}
function Profile() {
return <View>
<Text>Profile</Text>
</View>;
}
function FeedScreen() {
return (
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Details" component={Details} />
</Stack.Navigator>
);
}
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name="Feed" component={FeedScreen} />
<Tab.Screen name="Profile" component={Profile} />
</Tab.Navigator>
</NavigationContainer>
);
}
The navigation.navigate(...) part becomes a little more complicated but not too bad. See the example here. This one is basically opposite of your setup where the tabs are nested within a stack navigator.

react-navigation native-stack Stack Navigator Screen keep blank

I was following the React navigation to create the pages, however, I only get the blank page when I build the application.
https://reactnavigation.org/docs/hello-react-navigation
React navigation version
"#react-navigation/native": "^6.0.6",
"#react-navigation/native-stack": "^6.2.5",
"#react-navigation/stack": "^6.0.11",
Here is my full code on App.js
On this page, I created 3 function: HomeSc, HomeScCheck, DetailSc.
Only the HomeScCheck can show on the screen.
import * as React from 'react';
import { View, Text , SafeAreaView} from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
function HomeScCheck() {
return (
<View><Text style={{color:"red"}}>Home Screen Check</Text></View>
);
}
function HomeSc() {
return (
<View><Text>Home Screen</Text></View>
);
}
function DetailSc() {
return (
<View style={{ flex: 1}}>
<Text style={{color: '#333', fontSize:30}}>Detail Screen</Text>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<SafeAreaView>
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeSc} />
<Stack.Screen name="Detail" component={DetailSc} options={{ title: 'Overview' }} />
</Stack.Navigator>
</NavigationContainer>
<HomeScCheck/>
</SafeAreaView>
);
}
export default App;
As you were saying that you want to see the HomeScCheck screen as the first screen, you should see when the app is run.
So, to do that your code should look as the following code.
import { View, Text, SafeAreaView } from 'react-native';
import * as React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
function HomeScCheck() {
return (
<View>
<Text style={{ color: 'red' }}>Home Screen Check</Text>
</View>
);
}
function HomeSc() {
return (
<View>
<Text>Home Screen</Text>
</View>
);
}
function DetailSc() {
return (
<View style={{ flex: 1 }}>
<Text style={{ color: '#333', fontSize: 30 }}>Detail Screen</Text>
</View>
);
}
const Stack = createNativeStackNavigator();
function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home Check" component={HomeScCheck} />
<Stack.Screen name="Home" component={HomeSc} />
<Stack.Screen
name="Detail"
component={DetailSc}
options={{ title: 'Overview' }}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
export default App;
So, What I have done is that I have removed the <safeareaview> and <HomeScCheck> and I have created another <Stack.Screen> above the home <Stack.Screen>. Though this tells that the first <Stack.Screen> will be the first screen of the stack navigator.
Kindly remove safeAreaView and statusbar from the App.js file
only put Navigation inside the return

React DrawerNavigation Is Not Working (Nothing Happens) While I Drag To Open Side Menu

I'm trying to introduce DrawerNavigation under StackNavigation. My StackNavigation is working fine. But when I'm dragging the screen DrawerNavigation is not working. Nothing happens...No errors also.
I am using TouchableOpacity for the list items. Though I don't think so, is there any chance it is occurring due to the first touch on list-item??? If not, then can anyone point me out what the issue is? I really appreciate any help you can provide.
I have given my Navigator.Js code here and a video Url to understand better what is happening for my case.
Video URL - https://drive.google.com/file/d/1MhD3gB8Pp4tqbXr1HktOPa-2xOqW0xoA/view?usp=sharing
Instead of wrapping DrawerNavigator inside StackNavigator, wrap your StackNavigator inside DrawerNavigator.
Working Example: Expo Snack
Output:
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createDrawerNavigator } from '#react-navigation/drawer';
const Drawer = createDrawerNavigator();
const Stack = createStackNavigator();
const StackNav = () => {
return (
<Stack.Navigator>
<Stack.Screen name="Login" component={() => <Text>Login</Text>} />
<Stack.Screen name="Register" component={() => <Text>Register</Text>} />
</Stack.Navigator>
);
};
export default function App() {
return (
<View style={styles.container}>
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="Stack" component={StackNav} />
<Drawer.Screen
name="HomeNews"
component={() => (
<View style={styles.container}>
<Text>HomeNews</Text>
</View>
)}
/>
<Drawer.Screen
name="StateNews"
component={() => (
<View style={styles.container}>
<Text>StateNews</Text>
</View>
)}
/>
</Drawer.Navigator>
</NavigationContainer>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
});

react-navigation v5 - how to toggle drawer

I upgraded to react-navigation V5, and am so confused how to get the Drawer to work. I had a custom drawer before, but now I'm just trying to get a sample drawer working.
I am trying to open the drawer with this.props.navigation.dispatch(DrawerActions.toggleDrawer())
The action 'TOGGLE_DRAWER' was not handled by any navigator.
Is your screen inside a Drawer navigator?
Here are the relevant files:
MessagesStackRouter.js
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createDrawerNavigator } from '#react-navigation/drawer';
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
function DrawerNavigation() {
return (
<Drawer.Navigator
drawerType={"slide"}
>
<Drawer.Screen name="Dash" component={DashboardContainer} />
</Drawer.Navigator>
);
}
function MessagesStackRouter() {
return (
<NavigationContainer>
<Stack.Navigator
initalRoute="Login"
screenOptions={{ gestureEnabled: true, headerShown: false }}
>
<Stack.Screen name="Login" component={LoginView} />
<Stack.Screen name="DrawerNavigation" component={DrawerNavigation} />
<Stack.Screen name="Dashboard" component={DashboardContainer} />
</Stack.Navigator>
</NavigationContainer>
);
}
export default MessagesStackRouter;
App.js
return (
<View style={{flex:1, backgroundColor: 'white'}}>
<StatusBar hidden={true} />
<Provider store={createStore(reducers)}>
<MessagesScreenRouter/>
</Provider>
</View>
);
relevant parts of TopNavBar.js
import { DrawerActions } from '#react-navigation/native';
class TopNavBar extends Component {
constructor(props) {
super(props);
this.onBurgerBarPress = this.onBurgerBarPress.bind(this)
}
onBurgerBarPress() {
this.props.navigation.dispatch(DrawerActions.toggleDrawer())
}
render() {
return (
<View style={styles.navBar}>
<View style={{ flex: 1, flexDirection: 'row', justifyContent: 'space-between', marginTop: 10 }}>
<TouchableOpacity onPress={()=> this.onBurgerBarPress()}>
<Icon
name={"Menu"}
strokeWidth="1.5"
stroke={'#03A9F4' }
fill={'#03A9F4'}
/>
</TouchableOpacity>
</View>
</View>
)
}
};
const mapStateToProps = (state) => {
return {
onboarding: state.onboarding,
currentUser: state.currentUser
}
}
export default connect(mapStateToProps, actions)(TopNavBar);
You get an error because the screen where you have the drawer navigator is not rendered. You should nest the stack navigator inside the drawer navigator instead of drawer inside stack which will work better for your case.