React-native bottom navigation with stacknavigator - react-native

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.

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

Correct way of presenting a new screen with a stack?

I have a signup page with 4 steps (4 separate screens). On the first page, the user enters their username in a field, on the second page a display name, on the third their birthday, and on the fourth their password.
Here's my current signup screen file:
import React from 'react';
import { View, Text, Button } from 'react-native';
const SignupScreen = () => {
return (
<View>
<Text>First step</Text>
<Button
title="Next step"
/>
</View>
);
}
export default SignupScreen;
But I'm a bit confused as to how to present the next screen when the user taps the Button. How do I create a Stack here? Or would I do it in the App.js file?
Here is my App.js:
import { StatusBar } from 'expo-status-bar';
import { FlatList, StyleSheet, Text, View, TouchableHighlight } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import {
RootStack,
TabsStack,
SignupStack
} from './navigation/navigation';
export default function App() {
return (
<NavigationContainer>
<RootStack.Navigator>
<RootStack.Screen
name="Tabs"
options={{ headerShown: false }}
component={TabsStack}
/>
<RootStack.Screen
name="SignupStack"
options={{ headerShown: false }}
component={SignupStack}
/>
</RootStack.Navigator>
</NavigationContainer>
);
}
And here is my navigation.js file:
import React from 'react';
import { FlatList, StyleSheet, Text, View, TouchableHighlight } from 'react-native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import SignupScreen from '../screens/SignupScreen';
export const RootStack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();
const SignupNav = createNativeStackNavigator();
export const TabsStack = () => (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="History" component={SecondScreen} />
<Tab.Screen name="Third" component={ThirdScreen} />
<Tab.Screen name="Fourth" component={FourthScreen} />
</Tab.Navigator>
);
export const SignupStack = () => (
<SignupNav.Navigator>
<SignupNav.Screen
name="Signup"
component={SignupScreen}
options={{ headerTitle: 'Sign up' }}
/>
</SignupNav.Navigator>
);
function HomeScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Home</Text>
</View>
);
}
function SecondScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Second</Text>
</View>
);
}
function ThirdScreen() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<Text>Third</Text>
</View>
);
}
function FourthScreen({ navigation }) {
function onPressButton() {
navigation.navigate('SignupStack');
}
return (
<View>
<FlatList
data={[
{key: 'Signup'},
]}
renderItem={({item}) => <TouchableHighlight onPress={onPressButton} underlayColor="white"><Text>{item.key}</Text></TouchableHighlight>}
/>
</View>
);
}
What's the correct way of doing this?
Thank you
the best way that i know, make all the screen as component and import it in the signup screen
signup.js
/*
import all you component(pages) here...
*/
const [screen, setScreen] = useState(1)
{screen == 1 ? (
<ScreenOne
onNext={()=>setScreen(2)}
/>
) : screen == 2 ? (
<ScreenTwo
onNext={()=>setScreen(3)}
/>
) : screen == 3 ? (
<ScreenThree
onNext={()=>setScreen(4)}
/>
)
}
You can pass all your state and callback function from signup page to all the component get value from the component

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 Native - Update text after clicking button

I want to update the text after clicking button.
But couldn't find a way to do this.
The code is like:
import * as React from 'react';
import { View, Button, Text } from 'react-native';
import { NavigationContainer, CommonActions } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
function HomeScreen({ navigation }) {
const state = {
user: 'test',
};
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>{state.user}'s profile</Text>
<Button
title="Change user param"
onPress={() =>
navigation.dispatch({
...CommonActions.setParams({ user: 'Wojtek' }),
})
}
/>
</View>
);
}
const Stack = createStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
Expo example
I've tried navigation.setParams() and this.setState(), they couldn't work with the code I attached above.
You have to use hooks in functional components. So the code would be something like this:
import * as React from 'react';
import { View, Button, Text } from 'react-native';
import { NavigationContainer, CommonActions } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
function HomeScreen({ navigation }) {
const [user, setUser] = React.useState('test');
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>{user}'s profile</Text>
<Button
title="Change user param"
onPress={() => setUser("keidakira") }
/>
</View>
);
}
const Stack = createStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
Check it's working at Expo Link

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.