I have created a login screen for my expo react-native app. However, once the the user has logged in, at the home screen, I would like to show 3 icons at the bottom tab.But i am not sure how to create the bottom tabs. Essentially, there will be 3 tabs that need to be created (e.g. calendar, activity and settings).
App.js
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, Image } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import LoginScreen from './screens/Dashboard/LoginScreen';
import HomeScreen from './screens/Dashboard/HomeScreen';
const Stack = createNativeStackNavigator();
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen options={{ headerShown: false }} name="Login" component={LoginScreen} />
<Stack.Screen name="Home" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
HomeScreen.js
import { useNavigation } from '#react-navigation/core'
import React from 'react'
import { StyleSheet, Text, TouchableOpacity, View, Image } from 'react-native'
import { auth } from '../../firebase'
const HomeScreen = () => {
const navigation = useNavigation()
const handleSignOut = () => {
auth
.signOut()
.then(() => {
navigation.replace("Login")
})
.catch(error => alert(error.message))
}
return (
<View style={styles.container}>
<Text>Email: {auth.currentUser?.email}</Text>
<TouchableOpacity
onPress={handleSignOut}
style={styles.button}
>
<Text style={styles.buttonText}>Sign out</Text>
</TouchableOpacity>
</View>
)
}
export default HomeScreen
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
button: {
backgroundColor: '#0782F9',
width: '60%',
padding: 15,
borderRadius: 10,
alignItems: 'center',
marginTop: 40,
},
buttonText: {
color: 'white',
fontWeight: '700',
fontSize: 16,
},
image: {
width: 40,
height: 40,
},
})
Would appreciate your help. Thanks.
Create a component like shown in react navigation docs https://reactnavigation.org/docs/material-bottom-tab-navigator/#example and then replace the "HomeScreen" component with the newly create Tabs navigator component.
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen options={{ headerShown: false }} name="Login" component={LoginScreen} />
<Stack.Screen name="Home" component={MyTabs} />
</Stack.Navigator>
</NavigationContainer>
);
}
[1]: https://reactnavigation.org/docs/material-bottom-tab-navigator
Related
your texti'm tryng to navigate with the props navigation as a nested navigation and i'm getting this error
ERROR The action 'NAVIGATE' with payload {"name":"Man"} was not handled by any navigator.
Do you have a screen named 'Man'?
If you're trying to navigate to a screen in a nested navigator, see https://reactnavigation.org/docs/nesting-navigators#navigating-to-a-screen-in-a-nested-navigator.
This is a development-only warning and won't be shown in production.
i suspact that is becose i didnt set the screen but i dont wont to set the screen becose i wont it to render only when the user is clicking on the button
i'm tryng to navigate the component man
this is my code
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';
export default function Man() {
return (
<View style={styles.container}>
<Text>Man</Text>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
import { StatusBar } from "expo-status-bar";
import { StyleSheet, Text, View } from "react-native";
import { NavigationContainer } from "#react-navigation/native";
import { createBottomTabNavigator } from "#react-navigation/bottom-tabs"
import { useNavigation } from '#react-navigation/native';
import Home from "./screens/Home";
import Exhibition from "./screens/Exhibition";
import Cart from "./screens/Cart";
export default function App() {
const Tab = createBottomTabNavigator();
// const navigation = useNavigation();
return (
<NavigationContainer>
<Tab.Navigator >
<Tab.Screen name="Home" component={Home} />
<Tab.Screen name="Exhibition" component={Exhibition} />
<Tab.Screen name="Cart" component={Cart} />
</Tab.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
// marginLeft: 50
},
});
import { StatusBar } from "expo-status-bar";
import {createStackNavigator} from '#react-navigation/stack';
import {
FlatList,
Image,
StyleSheet,
Text,
TouchableOpacity,
View,
} from "react-native";
import { createNativeStackNavigator } from "#react-navigation/native-stack";
import { useState } from "react";
import { useNavigation, StackActions, useNavigationContainerRef } from "#react-navigation/native";
import Man from "./Man";
import Woman from './Woman'
export default function Home({navigation}: any) {
const navigationRef = useNavigationContainerRef()
const collections: { name: string; img: any; compo: any; key: number }[]= [
{
name: "man collection",
img: require("../assets/manModel.jpeg"),
compo: "Man",
key: 1,
},
{
name: "woman collection",
img: require("../assets/womanModel.jpg"),
compo: "Woman",
key: 2,
},
]
const Stack = createNativeStackNavigator();
// const navigation = useNavigation();
return (
<View style={styles.container}>
<FlatList
numColumns={2}
data={collections}
renderItem={({ item }) => (
<>
<TouchableOpacity
onPress={() => {
navigation.navigate('Man');
}}
>
<Image style={styles.image} source={item.img} />
<Text style={styles.title}>{item.name}</Text>
</TouchableOpacity>
</>
)}
/>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
image: {
width: 170,
height: 180,
margin: 15,
},
title: {
position: "absolute",
left: "15%",
right: "15%",
width: "70%",
top: 90,
fontSize: 17,
color: "white",
backgroundColor: "purple",
fontWeight: "bold",
textAlign: "center",
},
});
I'm facing a problem while trying to implement navigation drawer, i have stack and tab navigation working properly but once i initialize navigation drawer my page goes blank and once i comment the line my page starts working properly.
i don't know how to fix this and i need to learn how to make use of navigation drawer
import React from 'react';
import { StyleSheet, Text, View,Button } from 'react-native';
import { NavigationContainer,useNavigation } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();
const Drawer = createDrawerNavigator();
const Home = () => {
return(
<Stack.Navigator>
<Stack.Screen name="Dash" component={Dashboard} />
<Stack.Screen name="Login" component={LoginPage} />
</Stack.Navigator>
);
};
const Search = () => (
<View style={styles.color2}>
<Text style={styles.title}>Search</Text>
</View>
);
const Dashboard = () => {
const nav = useNavigation();
return (
<View style={styles.color3}>
<Text style={styles.title}>Dashboard</Text>
<Button title='Login' onPress={() => nav.navigate('Login') }></Button>
</View>
);
};
const LoginPage = () => (
<View style={styles.color2}>
<Text style={styles.title}>Login</Text>
</View>
);
const AppNavigator = () => (
<Tab.Navigator>
<Tab.Screen options={{headerShown: false}} name="Home" component={Home} />
<Tab.Screen name="Search" component={Search} />
</Tab.Navigator>
);
const App = () => (
<NavigationContainer>
<AppNavigator />
</NavigationContainer>
);
export default App;
const styles = StyleSheet.create({
layout: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
title: {
fontSize: 32,
marginBottom: 16,
},
color1: {
backgroundColor: 'red',
color: '#fff',
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
color2: {
backgroundColor: 'blue',
color: '#fff',
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
color3: {
backgroundColor: 'green',
color: '#fff',
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
Once i comment this line the page starts working properly const Drawer = createDrawerNavigator();
When i open my browser i found these error
Uncaught Error: Module parse failed: Unexpected token (4:9)
File was processed with these loaders:
* ./node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
| export * from "./reanimated1";
| export * from "./reanimated2";
> export * as default from "./Animated";
Thanks for all your contributions, I fix the problem already by adding
plugins: ['react-native-reanimated/plugin']
to my babel.config.js file
This is my first React Native app. I want to get the header hamburger icon to open the side bar (drawer) but it only read it as undefined. So I read that it´s not possible to implement openDrawer() on a header as it is not read as a "screen". I have not been able to understand how to change my code to make it work. Help appreciated.
My code:
//Header
import React from "react";
import { StyleSheet, View, Text, TouchableOpacity } from "react-native";
import { Ionicons } from "#expo/vector-icons";
export const Header = ({ navigation, title }) => {
const openMenu = () => {
navigation.openDrawer();
};
return (
<View style={styles.header}>
<TouchableOpacity onPress={openMenu} style={styles.icons}>
<Ionicons name="md-menu" size={28} color="white" />
</TouchableOpacity>
<View style={styles.headerTitle}>
<Text style={styles.headerText}>{title}Title for header</Text>
</View>
</View>
);
};
//Navigation screen
import React from "react";
import { NavigationContainer } from "#react-navigation/native";
import { createDrawerNavigator } from "#react-navigation/drawer";
import { Notifications } from "./screens/Notifications";
import { Profile } from "./screens/Profile";
import { Header } from "./screens/Header";
const Drawer = createDrawerNavigator();
export const Navigation = () => {
return (
<>
<Header />
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="Login" component={Login} />
<Drawer.Screen name="Profile" component={Profile} />
<Drawer.Screen name="Notifications" component={Notifications} />
</Drawer.Navigator>
</NavigationContainer>
</>
);
};
Firstly, create a folder called navigation where your App.js is located
Inside navigation folder create a file called AppNavigator.js
Then paste this inside AppNavigator.js
import React from "react";
import { createDrawerNavigator } from "#react-navigation/drawer";
import { Notifications } from "./screens/Notifications";
import { Profile } from "./screens/Profile";
const Drawer = createDrawerNavigator();
function AppNavigator() {
return (
<Drawer.Navigator screenOptions={{ headerShown: true }}>
<Drawer.Screen name="Profile" component={Profile} />
<Drawer.Screen name="Notifications" component={Notifications} />
</Drawer.Navigator>
);
}
export default AppNavigator;
In your App.js paste this code
import React from "react";
import { NavigationContainer } from "#react-navigation/native";
import AppNavigator from "./navigation/AppNavigator"
const App = () => {
return (
<NavigationContainer>
<AppNavigator />
</NavigationContainer>
);
};
export default App;
Your Login.js would look like this
import React, { useState } from "react";
import {
TouchableOpacity,
TextInput,
Text,
View,
StyleSheet,
} from "react-native";
export const Login = ({ navigation }) => {
const [userName, setUserName] = useState("");
const [password, setPassword] = useState("");
return (
<View style={styles.container}>
<Text style={styles.welcomeText}>Welcome to your App</Text>
<View style={styles.inputView}>
<TextInput
// required
style={styles.inputText}
placeholder="Email"
placeholderTextColor="#fff"
onChangeText={(value) => setUserName(value)}
defaultValue={userName}
/>
</View>
<View style={styles.inputView}>
<TextInput
// required
style={styles.inputText}
placeholder="Password"
placeholderTextColor="#fff"
onChangeText={(value) => setPassword(value)}
defaultValue={password}
/>
</View>
<TouchableOpacity>
<Text style={styles.forgot}>Forgot Password?</Text>
</TouchableOpacity>
<TouchableOpacity
style={styles.loginButton}
title="Login"
onPress={() => navigation.navigate("NavigationTest", { userName })}
>
<Text style={styles.loginText}>LOGIN</Text>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
welcomeText: {
color: "#fb5b5a",
fontWeight: "bold",
fontSize: 50,
textAlign: "center",
margin: 40,
},
inputView: {
width: "80%",
backgroundColor: "#465880",
borderRadius: 25,
height: 50,
marginBottom: 20,
justifyContent: "center",
padding: 20,
},
inputText: {
height: 50,
color: "white",
},
loginButton: {
width: "80%",
backgroundColor: "#fb5b5a",
borderRadius: 25,
height: 50,
alignItems: "center",
justifyContent: "center",
marginTop: 40,
marginBottom: 10,
},
forgot: {
color: "grey",
},
loginText: {
color: "#ffff",
fontWeight: "bold",
},
});
Building a Signal clone and trying to have my to be styled from my StyleSheet. Here is the code
import "react-native-gesture-handler";
import { StatusBar } from "expo-status-bar";
import React from "react";
import { StyleSheet, Text, View } from "react-native";
import { NavigationContainer } from "#react-navigation/native";
import LoginScreen from "./screens/LoginScreen";
import { createStackNavigator } from "#react-navigation/stack";
import RegisterScreen from "./screens/RegisterScreen";
const Stack = createStackNavigator();
const globalScreenOptions = {
headerStyle: { backgroundColor: "#2C6BED" },
headerTitleStyle: { color: "white" },
headerTintColor: "white",
};
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator screenOptions={globalScreenOptions}>
<Stack.Screen name="Login" component={LoginScreen} />
<Stack.Screen name="Register" component={RegisterScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
I have tried to put everything in a tag to get it to be affected by the StyleSheet, but that won't work either. I'm unable to find any other similar posts to this question
To use the styles created by StyleSheet.create, you need to actually use them in an element. For example (from the stylesheet docs):
import React from "react";
import { StyleSheet, Text, View } from "react-native";
const App = () => (
<View style={styles.container}> {/* <-- note style attribute */}
<Text style={styles.title}>React Native</Text>
</View>
);
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 24,
backgroundColor: "#eaeaea"
},
title: {
marginTop: 16,
paddingVertical: 8,
textAlign: "center",
}
});
export default App;
I am trying to add title and buttons to my home screen that is opened from drawer navigation. The following does not work(screen loads but no header) and i cant find documentation or sample on this that uses React Navigation v5. Did i miss something? This is the doc i am following.
<Drawer.Screen
name="Home"
component={HomeScreen}
title="Home Screen"
options={{
headerRight: () => (
<Button
onPress={() => alert("This is a button!")}
title="Info"
color="#fff"
/>
),
}}
/>
UPDATE: doing this on the screen didn't work as well.
const HomeScreen = (props) => {
return (
<Container>
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<Text>Home Screen2</Text>
</View>
</Container>
);
};
HomeScreen.navigationOptions = (props) => ({
title: "Home",
headerStyle: {
backgroundColor: "rgb(0, 145, 234)",
},
headerTintColor: "white",
headerTitleStyle: {
fontWeight: "bold",
color: "white",
},
});
export default HomeScreen;
From the option you put in, I guess you may want to add a Stack inside your Drawer navigation.
From the below example, when you go to the HomeStack, it will have a navigation bar and you can custom it using the option you put in.
(I also created a simple snack here: https://snack.expo.io/#gie3d/insane-ice-cream)
import React from 'react';
import { Text, View } from 'react-native';
import { NavigationContainer, DrawerActions } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { Ionicons } from '#expo/vector-icons';
const Stack = createStackNavigator();
const Drawer = createDrawerNavigator();
const HomeStack = () => (
<Stack.Navigator>
<Stack.Screen name="Home" component={Home} options={({navigation}) => ({
title: "Home",
headerStyle: {
backgroundColor: "rgb(0, 145, 234)",
},
headerTintColor: "white",
headerTitleStyle: {
fontWeight: "bold",
color: "white",
},
headerLeft: () => (
<Ionicons
name={'md-menu'}
size={24}
style={{ marginLeft: 10 }}
onPress={() =>
navigation.dispatch(DrawerActions.toggleDrawer())
}
/>
),
})} />
</Stack.Navigator>
);
const Home = () => {
return (
<View>
<Text>This is Home</Text>
</View>
)}
export default () => {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="HomeStack">
<Drawer.Screen name="HomeStack" component={HomeStack} />
<Drawer.Screen name="HomeNoStack" component={Home} />
</Drawer.Navigator>
</NavigationContainer>
);
}
You need to create the button on your screen too, like this.
import React from "react";
import {Text, View} from 'react-native';
export default class News extends React.Component {
static navigationOptions = ({navigation}) => {
return {
//headerLeft: --- PUT HERE YOU CUSTOM BUTTON (Use navigation.goBack() in onPress)
headerLeft:(<HeaderBackButton size={20} onPress={()=>{navigation.navigate('Home')}} color="#fff" tintColor="#fff"/>),
headerStyle: {
backgroundColor: 'rgb(0, 145, 234)',
},
headerTintColor: 'white',
headerTitleStyle:
{
fontWeight: 'bold',
color:'white' ,
//paddingTop:"2%",
},
}
}
render() {
return (
<View>
<Text> Here Leave the News!! </Text>
</View>
);
}
}