Screen title not centered - react-native

This is my HomeScreen.js:
import * as React from 'react';
import HomeScreenStyle from '../styles/ScreenStyles';
import { View, TouchableOpacity, Text, Image, StyleSheet } from 'react-native';
const HomeScreen = ({ navigation }) => {
return (
<View style={HomeScreenStyle.container}>
<Image source = {require("../assets/AppLogo.jpg")}/>
</View>
);
};
export default HomeScreen;
This is my HomeScreenStyle.js
import { StyleSheet } from 'react-native';
const HomeScreenStyle = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});
export default HomeScreenStyle;
And this is my navigator which configures the title:
import * as React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import HomeScreen from '../screens/HomeScreen'
const Stack = createNativeStackNavigator();
const MyStack = () => {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'Home' }}
/>
</Stack.Navigator>
</NavigationContainer>
);
};
export default MyStack;
As you can see in the photo the screen title is not centered, how can I achieve that?
thank you

Add the following headerTitleAlign: 'center' in the options so the stack screen will be
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'Home',headerTitleAlign: 'center' }}
/>

just add headerTitleAlign:'center' to screen options :
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'Home',headerTitleAlign:'center' }}
/>

Related

can not read property 'openDrawer' of undefined

i started to learn react native and i am getting error because i cant use openDrawer and i don't know where is the error.
i tried to follow the instructions on the react navigation web page.
below is my code
MainHeader
import React from 'react';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import Icon from '../../utils/Icon';
import {View} from 'react-native';
import {spacing} from '../../constants/theme';
const MainHeader = ({navigation}) => {
const insets = useSafeAreaInsets();
return (
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
alignContent: 'center',
paddingHorizontal: spacing.l,
marginTop: insets.top,
}}>
<Icon icon="Hamburger" onPress={() => navigation.openDrawer()} />
<Icon style={{width: 25, height: 25}} icon="Cart" onPress={() => {}} />
</View>
);
};
export default MainHeader;
MainNavigator
import React from 'react';
import {createStackNavigator} from '#react-navigation/stack';
import {NavigationContainer} from '#react-navigation/native';
import {StatusBar} from 'react-native';
import TabNavigator from './TabNavigator';
const Stack = createStackNavigator();
const MainNavigator = () => {
return (
<NavigationContainer>
<StatusBar hidden />
<Stack.Navigator>
<Stack.Screen
name="Root"
component={TabNavigator}
options={{
headerShown: false,
useNativeDriver: true,
gestureEnabled: false,
}}
/>
</Stack.Navigator>
</NavigationContainer>
);
};
export default MainNavigator;
TabNavigator
import React from 'react';
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
import {Animated} from 'react-native';
import Icon from '../utils/Icon';
import {colors, sizes} from '../constants/theme';
import PromoScreen from '../screens/PromoScreen';
import HomeNavigator from './HomeNavigator';
import ProductNavigator from './ProductNavigator';
import SearchNavigator from './SearchNavigator';
import ProfileNavigator from './ProfileNavigator';
import LoginScreen from '../screens/LoginScreen';
const tabs = [
{
name: 'Home',
screen: HomeNavigator,
},
{
name: 'Coffee',
screen: ProductNavigator,
},
{
name: 'Search',
screen: SearchNavigator,
},
{
name: 'Gift',
screen: PromoScreen,
},
{
name: 'Profile',
screen: LoginScreen,
},
];
const Tab = createBottomTabNavigator();
const TabNavigator = () => {
const offsetAnimation = React.useRef(new Animated.Value(0)).current;
return (
<>
<Tab.Navigator
initialRouteName="Home"
screenOptions={{
headerShown: false,
tabBarShowLabel: false,
}}>
{tabs.map(({name, screen}, index) => {
return (
<Tab.Screen
key={name}
name={name}
component={screen}
options={{
tabBarIcon: ({focused}) => {
return (
<Icon
icon={name}
size={40}
style={{
tintColor: focused ? colors.mainColor : colors.gray,
}}
/>
);
},
}}
listeners={{
focus: () => {
Animated.spring(offsetAnimation, {
toValue: index * (sizes.width / tabs.length),
useNativeDriver: true,
}).start();
},
}}
/>
);
})}
</Tab.Navigator>
</>
);
};
export default TabNavigator;
DrawNavigator
import React from 'react';
import {createDrawerNavigator} from '#react-navigation/drawer';
import {NavigationContainer} from '#react-navigation/native';
import HomeNavigator from './HomeNavigator';
const Drawer = createDrawerNavigator();
const MainDrawNavigator = () => {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeNavigator} />
</Drawer.Navigator>
</NavigationContainer>
);
};
export default MainDrawNavigator;
Home Navigator
import React from 'react';
import {createSharedElementStackNavigator} from 'react-navigation-shared-element';
import HomeScreen from '../screens/HomeScreen';
const Stack = createSharedElementStackNavigator();
const HomeNavigator = () => {
return (
<Stack.Navigator>
<Stack.Screen
name="HomeScreen"
component={HomeScreen}
options={{
headerShown: false,
useNativeDriver: true,
gestureEnabled: false,
}}
/>
</Stack.Navigator>
);
};
export default HomeNavigator;
HomeScreen
import React from 'react';
import {ScrollView, View} from 'react-native';
import MainHeader from '../components/Header/MainHeader';
import TitleHeader from '../components/Header/TitleHeader';
import MenuSlider from '../components/Home/MenuSlider';
import {Top_Sell, POPULAR} from '../data';
import SectionHeader from '../components/Header/SectionHeader';
import PopularList from '../components/Home/PopularList';
const HomeScreen = () => {
return (
<View style={{flex: 1, backgroundColor: '#fbfbfb'}}>
<MainHeader />
<TitleHeader mainTitle="Gợi ý" secondTitle="cho bạn" />
<ScrollView showsVerticalScrollIndicator={false}>
<MenuSlider list={Top_Sell} />
<SectionHeader title="Phổ biến" buttonTitle="More" onPress={() => {}} />
<PopularList list={POPULAR} />
</ScrollView>
</View>
);
};
export default HomeScreen;
I have tried several ways on stackOverflow but it doesn't work
You need to pass the navigation prop from HomeScreen to MainHeader to use it. Try replacing your HomeScreen with this:
const HomeScreen = ({ navigation }) => {
return (
<View style={{flex: 1, backgroundColor: '#fbfbfb'}}>
<MainHeader navigation={navigation} />
<TitleHeader mainTitle="Gợi ý" secondTitle="cho bạn" />
<ScrollView showsVerticalScrollIndicator={false}>
<MenuSlider list={Top_Sell} />
<SectionHeader title="Phổ biến" buttonTitle="More" onPress={() => {}} />
<PopularList list={POPULAR} />
</ScrollView>
</View>
);
};
please try this one. it seems that there is some issue with navigation state. check this one it will work.
based on your comment you may forgot to install some packages that are mandatory without that navigation won't work properly.
Please check for these.
#react-navigation/drawer,
#react-navigation/native-stack,
react-native-gesture-handler,
react-native-screens,
react-native-pager-view
[react-native-reanimated][1]
first configure these library , clean your project, delete it from device , rebuild and cheers!!
then. try this one
import React from 'react';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import Icon from '../../utils/Icon';
import {View} from 'react-native';
import {spacing} from '../../constants/theme';
import { useNavigation } from '#react-navigation/native';
const MainHeader = ({}) => {
const navigation = useNavigation();
const insets = useSafeAreaInsets();
return (
<View
style={{
flexDirection: 'row',
justifyContent: 'space-between',
alignContent: 'center',
paddingHorizontal: spacing.l,
marginTop: insets.top,
}}>
<Icon icon="Hamburger" onPress={() => navigation.openDrawer()} />
<Icon style={{width: 25, height: 25}} icon="Cart" onPress={() => {}} />
</View>
);
};
export default MainHeader;

Tab.Navigator props is not shown

I am new to react-native.
I want to access the tab Bar Options property of the Tab Navigator tag but it is shown.
Does any know the how to solve this?
here is my code:
import React from 'react';
import {View, StyleSheet, SafeAreaView, Text} from 'react-native';
import {Na vigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import HomeScreen from './app/screens/HomeScreen';
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();
export default function App() {
return (
<NavigationContainer>
<Tab.Navigator {/* HERE I Want to use the PROPS!!!!!!! */} >
<Tab.Screen />
</Tab.Navigator>
</NavigationContainer>
);
}
function HomeStack() {
return (
<Stack.Navigator
initialRouteName="HomeScreen"
screenOptions={{
headerStyle: {backgroundColor: '#841548'},
headerTintColor: 'white',
headerTitleStyle: {fontWeight: 'bold'},
}}>
<Stack.Screen
name="HomeScreen"
component={HomeScreen}
options={{title: 'Home Page'}}
/>
</Stack.Navigator>
);
}
const styles = StyleSheet.create({
container: {flex: 1, backgroundColor: 'white'},
});
In case you wanna implement a custom TabBar, you can access props like below:
<Tab.Navigator tabBar={props => <CustomTabBar {...props} />}>
{...}
</Tab.Navigator>

How to pass data through stack navigation to a specific screen on react native tabs?

I'm creating a bottom tabs in react native, which will have two screens Home and News.
But first, user will need to Sign In and the users data will be passed from the login screen to Home screen. How do i pass those data. By using
navigation.navigate('Home', {Name: Name});
I can successfuly retrieve the data in Homescreen, if I just use two screen(Login and Home in a stack). However, when I change to navigate to the tabs(which includes Home and News), it doesnt work with error 'Undefined is not an object(evaluating 'route.params.Name'.
May you guys show me which part did I miss?
Here's the app.js code.
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import HomeScreen from './homescreen';
import NewsScreen from './newsscreen';
import LoginScreen from './loginscreen';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { createStackNavigator } from '#react-navigation/stack';
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator>
<Tab.Screen name="Home" component={HomeScreen} />
<Tab.Screen name="News" component={NewsScreen} />
</Tab.Navigator>
);
}
const LoginStack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<LoginStack.Navigator screenOptions={{headerShown: false}}
initialRouteName="Login">
<LoginStack.Screen name="Login"component={LoginScreen}/>
<LoginStack.Screen name="MyTabs" component={MyTabs} />
</LoginStack.Navigator>
</NavigationContainer>
);
}
export default App;
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Following is the homescreen code:
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
export default function HomeScreen({route, navigation}) {
var Name = route.params.Name;
return (
<View style={styles.container}>
<Text>{Name}</Text>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
And finally here's the login code:
import { StatusBar } from 'expo-status-bar';
import React from 'react';
import { StyleSheet, Text, View, TouchableOpacity } from 'react-native';
export default function LoginScreen({navigation}) {
const Name = 'Boy';
const login = () => {
navigation.navigate('MyTabs', {Name: 'Boy'});}
return (
<View style={styles.container}>
<Text>LoginScreen</Text>
<TouchableOpacity
onPress={login}
><Text
>LOGIN</Text>
</TouchableOpacity>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
})
I'm trying to learn how to pass data from a screen to another screen, in which the screen is located inside a tab stack. I hope you guys can understand the question and provide me with your opinion and solution. Thanks.
Output:
It needed just this little modification in MyTabs component:
function MyTabs({ navigation, route }) {
const { name } = route.params;
console.log(name);
return (
<Tab.Navigator>
<Tab.Screen
name="Home"
component={() => <HomeScreen name={route.params.name} />}
/>
<Tab.Screen name="News" component={NewsScreen} />
</Tab.Navigator>
);
}
Here is the working solution:
App.js
import * as React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
import HomeScreen from './home';
import NewsScreen from './newscreen';
import LoginScreen from './login';
// You can import from local files
const Tab = createBottomTabNavigator();
function MyTabs({ navigation, route }) {
const { name } = route.params;
console.log(name);
return (
<Tab.Navigator>
<Tab.Screen
name="Home"
component={() => <HomeScreen name={route.params.name} />}
/>
<Tab.Screen name="News" component={NewsScreen} />
</Tab.Navigator>
);
}
const LoginStack = createStackNavigator();
function App() {
return (
<NavigationContainer>
<LoginStack.Navigator
screenOptions={{ headerShown: true }}
initialRouteName="Login">
<LoginStack.Screen name="Login" component={LoginScreen} />
<LoginStack.Screen name="MyTabs" component={MyTabs} />
</LoginStack.Navigator>
</NavigationContainer>
);
}
export default App;
LoginScreen
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import React from "react";
export default function LoginScreen({ navigation }) {
const Name = 'Name From Login Screen';
const login = () => {
console.log("hi");
navigation.navigate('MyTabs', { name : Name });
}
return (
<View style={styles.container}>
<View style={styles.bottomView}>
<TouchableOpacity onPress={login} style={styles.button}>
<Text style={styles.textStyle}>LOGIN</Text>
</TouchableOpacity>
</View>
</View>
);
}
Home.js
import { Text, View, StyleSheet } from 'react-native';
import React from "react";
export default function HomeScreen({route, navigation, name}) {
console.log("***",name)
return (
<View style={styles.container}>
<Text style={styles.name}>{name}</Text>
</View>
);
}
Working Expo Snack example.
It's a little complicated to explain react native screens once you start combining bottomtabnavigator and stack navigator and even drawernavigation.
you may need to create stack navigation inside tab navigation like this.
//creating a separate stack within your tab
const HomeStack = createStackNavigator()
const HomeStackNavigator = () => {
return (
<HomeStack.Navigator screenOptions={{headerShown: false}}
initialRouteName="HomeScreen">
<HomeStack.Screen name="Home"component={HomeScreen}/>
</HomeStack.Navigator>
)
}
const Tab = createBottomTabNavigator();
function MyTabs() {
return (
<Tab.Navigator initialRouteName="HomeStackNavigator">
<Tab.Screen name="HomeStackNavigator" component={HomeStackNavigator} />
<Tab.Screen name="News" component={NewsScreen} />
</Tab.Navigator>
);
}
I believe, different navigators doesn't really talk to each other well. If you are using different navigator be prepare to nest stack navigators inside them.
The idea is, the parent of each display component should be a stack navigator. This will also allow you to better control your screenOptions.

Bottom tab bar should not occur anywhere but only on the first initial screen that renders via Webview in React Native

I have a webview component in my project, where the flow being =>
The bottomTabBar opens the initial screen of the url that is given to Webview source prop, which should remain, when any link is clicked on the webview and it moves to another screen, the bottomtabbar should not come up.
Below is my WebviewScreen code :
import React, {Component} from 'react';
import {WebView} from 'react-native-webview';
import {View, SafeAreaView, ActivityIndicator} from 'react-native';
export default class ConsultationHomeScreen extends Component {
renderLoadingView = () => {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<ActivityIndicator size="large" />
</View>
);
};
render() {
const {url} = this.props.route.params;
return (
<SafeAreaView style={{flex: 1}}>
<WebView
source={{uri: url}}
renderLoading={this.renderLoadingView}
startInLoadingState={true}
ref={(ref) => {
this.webview = ref;
}}
onNavigationStateChange={(event) => {
if (event.url !== url) {
this.webview.stopLoading();
}
}}
/>
</SafeAreaView>
);
}
}
And Appnavigation.js
import * as React from 'react';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import {createBottomTabNavigator} from '#react-navigation/bottom-tabs';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import LoginScreen from '../screens/authentication/LoginScreen';
import OtpScreen from '../screens/authentication/OtpScreen';
import AddChild from '../screens/Child/AddChild';
import AcceptInviteScreen from '../screens/AcceptInviteScreen';
import ConsultationHomeScreen from '../screens/ConsultationHomeScreen';
import HomeScreen from '../screens/HomeScreen/HomeScreen';
import PlansScreen from '../screens/PlansScreen';
const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();
function BottomTabBar() {
return (
<Tab.Navigator
lazy={false}
tabBarOptions={{
labelStyle: {
color: '#FF1493',
fontSize: 15,
},
}}>
<Tab.Screen
name="Home"
component={HomeScreen}
options={{
tabBarIcon: () => {
<MaterialIcon name="home" color="#FF1493" size={20} />;
},
}}
/>
<Tab.Screen
name="Consult"
component={ConsultationHomeScreen}
initialParams={{
url: 'some link',
}}
/>
<Tab.Screen name="Plans" component={PlansScreen} />
</Tab.Navigator>
);
}
export default function AppNavigation() {
return (
<NavigationContainer>
<Stack.Navigator headerMode="none">
<Stack.Screen name="login" component={LoginScreen} />
<Stack.Screen name="otp" component={OtpScreen} />
<Stack.Screen name="addchild" component={AddChild} />
<Stack.Screen
name="acceptinvitescreen"
component={AcceptInviteScreen}
/>
<Stack.Screen name="home" component={BottomTabBar} />
</Stack.Navigator>
</NavigationContainer>
);
}
However, am unable to remove the bottomtabbar,could anyone please suggest how should I implement this behaviour?
Step1-> Webview initial screen renders and has bottomtabtabr
Step2-> Link clicked on the initial screen and navigates to next screen handled by web source
Step3->Bottom tab bar should not occur anywhere but only on the first initial screen
Please,any suggestion would be appreciated and let me know if anything else is required for better understanding.
I tested this modification in your source code and it works like a charm.
GIT difference in WebviewScreen.js :
## -23,6 +23,7 ## export default class ConsultationHomeScreen extends Component {
}}
onNavigationStateChange={(event) => {
if (event.url !== url) {
+ this.props.navigation.setOptions({ tabBarVisible: false });
this.webview.stopLoading();
}
}}
Let me know if you have any issue.

Setting up customizable Header in React Native

I wish to create Header for my Notes Storage App on React Native. I have Tried using stackNavigator till now but I am caught up on how to add menu icon which onPres will open the Drawer. I tried using HeaderLeft in stackDesignHead but it gives an error. Also using a FAB is not recommended.
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import HomePage from './src/HomePage/HomePage';
import NotesFolder from './src/notes';
import CreateNewFolder from './src/CreateNewFolder';
import Icon from 'react-native-vector-icons/Ionicons';
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 stackDesignHead = {
title: "Notes Classifier",
headerTintColor:"white",
headerStyle:{
backgroundColor:"#fcba03"
},
headerTitleStyle: {
fontWeight: 'bold',
},
headerTitleAlign: 'center'
}
function LeftDrawer () {
return(
<Stack.Navigator>
<Stack.Screen
name="HomePage"
component={HomePage}
options={stackDesignHead}
/>
<Stack.Screen
name="NotesFolder"
component={NotesFolder}
options={{...stackDesignHead,title:"Notes"}}
/>
<Stack.Screen
name="CreateNewFolder"
component={CreateNewFolder}
options={{...stackDesignHead,title:"+ new Folder"}}
/>
</Stack.Navigator>
)
}
const menuDesignHead = {
title: "Notes Classifier",
headerTintColor:"white",
headerStyle:{
backgroundColor:"#fcba03"
},
headerTitleStyle: {
fontWeight: 'bold',
},
headerTitleAlign: 'center'
}
function App () {
return(
<View style={styles.container}>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen
name="Home"
component={LeftDrawer}
options={{menuDesignHead}}
/>
</Drawer.Navigator>
</View>
);
}
export default()=>{
return(
<NavigationContainer>
<App/>
</NavigationContainer>
)
}
I am new to react native and unaware of various ways to create header.
Provides a way to create your own custom headers in React-navigation documents.
Replacing the title with a custom component
Sometimes you need more control than just changing the text and styles of your title -- for example, you may want to render an image in place of the title, or make the title into a button. In these cases you can completely override the component used for the title and provide your own.
Example
function LogoTitle() {
return (
<Image
style={{ width: 50, height: 50 }}
source={require('#expo/snack-static/react-native-logo.png')}
/>
);
}
function StackScreen() {
return (
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ headerTitle: props => <LogoTitle {...props} /> }}
/>
</Stack.Navigator>
);
}