How can i change Navigationbar title in React Native - reactjs

i am new in react native. i am create new basic app with navigation bar.
i have two screen.
Home
List
i want to change both navigation bar title With "Home Screen" and "List Screen"
i have one button in home Screen. when i tap on button it navigate to list screen.
my problem is i can't change the title in list screen.
App.js
import { createAppContainer } from '#react-navigation/native';
import { createStackNavigator } from 'react-navigation-stack';
import HomeScreen from './src/screens/HomeScreen';
import ListScreen from './src/screens/ListScreen';
const navigator = createStackNavigator({
Home: HomeScreen,
List: ListScreen
},{
initialRouteName: 'Home',
defaultNavigationOptions:{
title: 'Home Screen'
}
}
);
export default createAppContainer(navigator);
HomeScreen.js
import React from 'react';
import { View, Text, StyleSheet, Button, TouchableOpacity, Stack} from 'react-native';
const HomeScreen = props => {
return(
<View style={styles.container}>
<TouchableOpacity
style={styles.button}
onPress={() => props.navigation.navigate('List')}
>
<Text>START</Text>
</TouchableOpacity>
</View>
);
};
ListScreen.js
import React from 'react';
import { View, Text, StyleSheet, Button } from 'react-native';
const ListScreen = () => {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>List Screen</Text>
</View>
);
};
const styles = StyleSheet.create({
});
export default ListScreen;
i am use expo-cli.
please help me.

If we put defaultNavigationOptions in createStackNavigator then it might not be possible to update the screen header component so to update the header for screens separately then we have to specify individual navigationOptions.
we can create a stack navigator, try the below way to manage headers dynamically.
const HomeNavigator = createStackNavigator({
Home: {
screen: HomeScreen,
navigationOptions: {
headerShown: true,
headerTitle: "Home"
}
}
})
we also can manage the header from screens as below another method:
const LoginScreen = props => {
return <View />
}
LoginScreen.navigationOptions = navData => {
return {
headerTitle: "Login",
headerTransparent: true,
headerShown: false
}
}

I assume you are using React Navigation v5, you may always refer to their code sample here.
If you are lazy to read their sample, their code snippet is as below
function StackScreen() {
return (
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ title: 'My home' }}
/>
</Stack.Navigator>
);
}
Below is a sample code from me, which you can use..
StackNavigator.js - (You can name whatever you want)
import * as React from 'react';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import ScreenA from '../Containers/ScreenA';
import ScreenB from '../Containers/ScreenB';
const Stack = createStackNavigator();
const AppFlow = () => {
return (
<NavigationContainer>
<Stack.Navigator name="Test App">
<Stack.Screen
name="First"
component={ScreenA}
options={{headerShown: true, title: 'Screen A Title'}}
/>
<Stack.Screen
name="Second"
component={ScreenB}
options={{headerShown: true, title: 'Screen B Title'}}
/>
</Stack.Navigator>
</NavigationContainer>
);
};
const MainStackNavigator = () => {
return AppFlow();
};
export default MainStackNavigator;
First.JS - (You can name whatever you want) Then at this "First" screen, you may navigate to "Second" screen by the following code
<TouchableOpacity
style={styles.button}
onPress={() => props.navigation.navigate('Second')}
>
<Text>START</Text>
</TouchableOpacity>

Related

Reactive navigation error: The action 'NAVIGATE' with payload {"name":"Dict"} was not handled by any navigator

I am a beginner of react native. After reading the reactive navigation basics, I'm trying to build my personal app. However, I have a difficulty of navigation to another components.
I only have the following components:
app.js
import { StatusBar } from 'expo-status-bar';
import { Button, StyleSheet, Text, View, TextInput, Image } from 'react-native';
import * as React from 'react';
import { NavigationContainer, StackActions } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import Dict from './dict';
const Stack = createNativeStackNavigator();
const HomeScreen = ({ navigation }) => {
return (
<View style={{ height: '100%' }}>
<View style={{
height: '15%', backgroundColor: 'powderblue', flexDirection:'row'
}} />
<Text>This is a test</Text>
<Button title="Go to Dictionary" onPress={() => navigation.navigate('Dict')}/>
</View>
);
};
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ headerShown: false }}
/>
</Stack.Navigator>
</NavigationContainer>
);
}
dict.js
import React from 'react';
import { Text } from 'react-native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
function Dict () {
return (
<Text>Hello, I am your cat!</Text>
);
}
export default Dict;
When I click the button Go to Dictionary, I've received the following error message:
The action 'NAVIGATE' with payload {"name":"Dict"} was not handled by any navigator.
Do you have a screen named 'Dict'?
What I want to achieve is jump to the dictionary page via a button click. Thank you for your help!
You have to create your Dict screen in your Navigator, try this:
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen
name="Home"
component={HomeScreen}
options={{ headerShown: false }}
/>
<Stack.Screen
name="Dict"
component={Dict}
options={{ headerShown: false }}
/>
</Stack.Navigator>
</NavigationContainer>
);
}

onPress function for DrawerNavigator

I have created a DrawerNavigator in my react native app which looks like this.
I just dont like the default header that react- native gives. So I wanna access it through an icon. I guess also using the onPress condition
import { createStackNavigator } from '#react-navigation/stack';
import { createDrawerNavigator } from '#react-navigation/drawer';
// importing of all screens
const Drawer = createDrawerNavigator();
const DrawerContent = () => {
return (
<Drawer.Navigator>
<Drawer.Screen
name="Home"
component={CategoryStack}
/>
<Drawer.Screen name="Aboutus" component={Aboutus} />
<Drawer.Screen name="Interest Recieved" component={InterestRecieved} />
</Drawer.Navigator>
);
};
const Stack = createStackNavigator();
const MainStack = () => {
return (
<Stack.Navigator>
<Stack.Screen
name="Loading"
component={Loading}
options={{ headerShown: false }}
/>
</Stack.Navigator>
);
};
export default MainStack;
How do I open it using an onPress of an icon?
Thanks!
React navigation useNavigation hook expose drawer actions - toggleDrawer,openDrawer and closeDrawer event handlers which you can use to open or close drawer.
import React from "react";
import { View, Text, StyleSheet, Pressable } from "react-native";
import { useNavigation } from "#react-navigation/native";
const ToggleDrawer = () => {
const { toggleDrawer,closeDrawer,openDrawer } = useNavigation();
return (
<Pressable onPress={toggleDrawer}>{/** Add your Icon Here */}</Pressable>
);
};
You can check in-depth drawer example
In the header options you can customize the header and add for example an icon on the top left side like this.
useLayoutEffect(() => {
navigation.setOptions({
title: 'ScreenName',
headerLeft: () => (
<View style={{ marginLeft: 15 }}>
<TouchableOpacity onPress={() => navigation.openDrawer()} >
{*INSERT ICON HERE*}
</TouchableOpacity>
</View>
),
})
})

React Native call navigator inside child navigator screen

I have a main navigator in app.js
import React from 'react';
import LoginScreen from './src/screens/LoginScreen';
import HomeScreen from './src/screens/HomeScreen';
import { Image } from 'react-native';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import { Constans } from './src/constants/Constant';
import SignupScreen from './src/screens/SignupScreen';
import { EventScreen } from './src/screens/EventScreen';
const navigator = createStackNavigator(
{
Login: {
screen: LoginScreen,
navigationOptions: {
headerShown: false
}
},
SignUp: {
screen: SignupScreen,
navigationOptions: {
headerShown: false
}
},
Home: {
screen: HomeScreen,
navigationOptions: {
headerLeft:()=>false,
headerTitle:()=> (
<Image style={{width:35,height:35}} source={Constans.logoImage}/>
)
}
},
Event:{
screen:EventScreen,
navigationOptions: {
headerLeft:()=>false,
headerTitle:()=> (
<Image style={{width:35,height:35}} source={Constans.logoImage}/>
)
}
}
},
{
initialRouteName: 'Home'
}
);
const AppContainer = createAppContainer(navigator);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
and when I go HomeScreen I have also menu navigator.
import React from 'react';
import Icon from 'react-native-vector-icons/FontAwesome';
import { NavigationContainer } from '#react-navigation/native';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { TabEventsScreen } from './TabEventsScreen';
import { TabForYouScreen } from './TabForYouScreen';
import { TabProfileScreen } from './TabProfileScreen';
const Tab = createBottomTabNavigator();
export default function HomeScreen() {
return (
<NavigationContainer>
<Tab.Navigator
screenOptions=
{
({ route }) =>
(
{
tabBarIcon: ({ focused, color }) =>
{
return <Icon
name={route.name === 'Explore' ? "globe" : route.name === 'Profile' ? 'user' : route.name === 'Wallet' ? 'money' :'star'}
size={focused ? 32: 24}
color={color} />;
}
}
)
}
tabBarOptions=
{
{
activeTintColor: '#1F7A8C',
inactiveTintColor: 'gray',
}
}>
<Tab.Screen name="Explore" component={TabEventsScreen} />
<Tab.Screen name="For You" component={TabForYouScreen} />
<Tab.Screen name="Wallet" component={TabProfileScreen} />
<Tab.Screen name="Profile" component={TabProfileScreen} />
</Tab.Navigator>
</NavigationContainer>
);
}
in one tab screen I am trying to navigate Event screen of main navigator. How can I do it?
import React, { useState, useEffect } from 'react';
import { Constans } from './../constants/Constant';
import { View, ImageBackground, Text, ScrollView } from 'react-native';
import { TabEventsScreenStyle } from './../styles/TabEventsScreenStyle';
import { IncomingEvents } from './../services/TabEventsService';
import { EventCard } from './../components/Eventcard'
export function TabEventsScreen({navigation}) {
const [events, setEvents] = useState([]);
const [page, setPage] = useState(1);
_getEvents = () => {
return IncomingEvents(1, page, 20);
}
useEffect(() => {
setEvents(_getEvents().Events);
});
_OnButtonPress=(key)=>{
console.log(navigation)
navigation.navigate('Event',{itemId:key});
}
return (
<ScrollView>
<ImageBackground source={Constans.homeBackGroundImage} style={TabEventsScreenStyle.backgroundImage} >
<Text style={TabEventsScreenStyle.title}>Incoming Events</Text>
<View>
{
events.map(el =>
<Text style={TabEventsScreenStyle.text} onPress={()=> this._OnButtonPress(el.key)}>
<EventCard key={el.key} data={el}></EventCard>
</Text>
)
}
</View>
</ImageBackground>
</ScrollView>
);
}
my error is
The action 'NAVIGATE' with payload
{"name":"Event","params":{"itemId":1}} was not handled by any
navigator.
Do you have a screen named 'Event'?
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.
I also tried
const parent_nav=navigation.dangerouslyGetParent();
console.log(navigation);
parent_nav.navigate('Event',{itemId:key});
but parent_nav is undefined
Thanks in advance
You can navigate as if all screens were at the same level.
Navigation actions are handled by current navigator and bubble up if couldn't be handled
For example, if you're calling navigation.goBack() in a nested screen, it'll only go back in the parent navigator if you're already on the first screen of the navigator. Other actions such as navigate work similarly, i.e. navigation will happen in the nested navigator and if the nested navigator couldn't handle it, then the parent navigator will try to handle it. In the above example, when calling navigate('Messages'), inside Feed screen, the nested tab navigator will handle it, but if you call navigate('Settings'), the parent stack navigator will handle it.
The source.
When you navigate, it will try to find your screen in the current navigation and if it failed, then will try with the parent until the root navigation.
Wrap your AppContainer with NavigationContainer instead of the TabNavigator, so that both the StackNavigator and TabNavigator use the same navigation prop
export default class App extends React.Component {
render() {
return(
<NavigationContainer>
<AppContainer />
<NavigationContainer/>
)}
}
And remove NavigationContainer from the TabNavigator
Here is how I nested Stack and Tab Navigator
import React from 'react';
import {Dimensions, StatusBar, StyleSheet} from 'react-native';
import {createMaterialBottomTabNavigator} from '#react-navigation/material-bottom-tabs';
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import AScreen from './AScreen';
import BScreen from './BScreen';
import CScreen from './CScreen';
import DScreen from './DScreen';
import A from './a';
import B from './B';
import C from './C';
import D from './D';
const Tab = createMaterialBottomTabNavigator();
const Stack = createStackNavigator();
const BottomTab = () => {
return (
<Tab.Navigator
activeColor="#ff6362"
backBehavior="initialRoute"
barStyle={{backgroundColor: '#000000'}}>
<Tab.Screen
name="A"
component={AScreen}
options={{
tabBarLabel: 'A',
tabBarIcon: ({color}) => (
<MaterialCommunityIcons name="book-open" color={color} size={26} />
),
}}
/>
<Tab.Screen
name="B"
component={BScreen}
options={{
tabBarLabel: 'B',
tabBarIcon: ({color}) => (
<MaterialIcons name="people" color={color} size={26} />
),
}}
/>
<Tab.Screen
name="C"
component={CScreen}
options={{
tabBarLabel: 'C',
tabBarIcon: ({color}) => (
<MaterialIcons name="people" color={color} size={26} />
),
}}
/>
<Tab.Screen
name="D"
component={DScreen}
options={{
tabBarLabel: 'D',
tabBarIcon: ({color}) => (
<MaterialIcons name="person-pin" color={color} size={26} />
),
}}
/>
</Tab.Navigator>
);
};
export default function AdminScreen(props) {
return (
<NavigationContainer>
<StatusBar hidden />
<Stack.Navigator headerMode="none">
<Stack.Screen name="BottomTab" component={BottomTab} />
<Stack.Screen name="A" component={A} />
<Stack.Screen name="B" component={B} />
<Stack.Screen name="C" component={C} />
<Stack.Screen name="D" component={D} />
</Stack.Navigator>
</NavigationContainer>
);
}

expo icons on the bottom tab navigator are not showing

I'm currently doing a react-native course and I started implementing my own code for the styling part. I have an issue with icons not showing and I can't seem to find a problem. I have been trying to implement the icon on the bookcase tab, but it doesn't appear on it, and also I don't get an error message on the expo.
import React from 'react';
import { createBottomTabNavigator } from 'react-navigation-tabs'
import { createAppContainer, createSwitchNavigator} from 'react-navigation';
import { View, StyleSheet } from 'react-native';
import { Text, Button, Input } from 'react-native-elements';
import {createStackNavigator} from 'react-navigation-stack';
import { Ionicons } from '#expo/vector-icons';
const switchNavigator = createSwitchNavigator({
ResolveAuth: ResolveAuthScreen,
loginFlow: createStackNavigator ({
Signin: signin,
Signup: signup,
}),
mainFlow: createBottomTabNavigator({
Bookcase: bookcase,
Explore: explore,
Profile: profile
}, {
tabBarOptions: {
activeTintColor: 'red',
inactiveTintColor: 'grey',
showIcon: true,
}},
{
Bookcase:{
screen:bookcase,
navigationOptions:{
tabBarLabel:'Bookcase',
tabBarIcon:({ tintColor })=>(
<Ionicons name="ios-home" color={tintColor} size={2}/>
)
}
}
}
)
});
const App = createAppContainer(switchNavigator)
export default () => {
return (
<AuthProvider>
<App ref ={(navigator) => {setNavigator(navigator)}} />
</AuthProvider>
);
};
If you are using react-navigation v5, then is preferred way to implement bottomStackNavigation. This code will render icons and its color according to active as well as inactive state. You have to pass options property to individual screen tab in react-navigation v5.
const BottomNavigator = () => {
const BottomNavigation = createBottomTabNavigator();
return (
<BottomNavigation.Navigator>
<BottomNavigation.Screen
name="Home"
component={HomeStack}
options={{
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="home" color={color} size={size} />
),
}}
/>
<BottomNavigation.Screen
name="Exam"
component={ExamStack}
options={{
tabBarIcon: ({ color, size }) => (
<MaterialCommunityIcons name="book" color={color} size={size} />
),
}}
/>
</BottomNavigation.Navigator>
);
};

when navigating between a view A to a view B it automatically returns to view A using createSwitchNavigator

This is the structure of my navigation in which I have 3 components, and I have a sidemu (drawer), but I do not want the sidemenu to be seen in login, so I place the "Detail" component in the "LoginStack" . The sidemenu only is showed in Home component.
the behavior occurs of the gif, why can this happen?
usernavigation.js
import React from "react";
import { createAppContainer, createSwitchNavigator } from "react-navigation";
import { createStackNavigator } from "react-navigation-stack";
import { createDrawerNavigator } from "react-navigation-drawer";
import SideBar from "../components/SideBar/SideBar";
import { STYLES } from "../styles/Styles";
import LoginScreen from "../screens/Login/Login";
import HomeScreen from "../screens/Home/Home";
import DetailScreen from "../screens/DetailScreen/DetailScreen ";
//Aqui se debe incluir las screen que no deben mostrar el drawer
const LoginStack = createStackNavigator(
{
Login: {
screen: LoginScreen,
navigationOptions: {
title: "Login",
headerLeft: null,
header: null
}
},
Detail: {
screen: DetailScreen,
navigationOptions: {
title: "Detail container",
headerStyle: STYLES.bgHeaderBack,
headerTintColor: "#fff",
headerMode: "none"
}
}
},
{
initialRouteName: "Login"
}
);
const HomeStack = createStackNavigator(
{
Home: {
screen: HomeScreen,
navigationOptions: {
title: "Home",
headerLeft: null,
header: null
}
}
},
{
initialRouteName: "Home",
headerMode: "none"
}
);
const DrawerStack = createDrawerNavigator(
{
Home: {
screen: HomeStack
}
},
{
contentComponent: SideBar
}
);
const switchNavigator = createSwitchNavigator(
{
LoginStack: LoginStack,
HomeStack: DrawerStack
},
{
headerMode: "none",
initialRouteName: "LoginStack"
}
);
const AppContainer = createAppContainer(switchNavigator);
export default AppContainer;
this is the component DetailScreen
import React from "react";
import { StyleSheet } from "react-native";
import { STYLES } from "../../styles/Styles";
import {
Container,
Header,
Title,
Left,
Icon,
Right,
Button,
Body,
Content,
Text,
Card,
CardItem
} from "native-base";
const ContainerDetail = props => {
return (
<Container>
<Header style={STYLES.bgAzulPatios}>
<Left>
<Button transparent onPress={() => props.navigation.goBack()}>
<Icon name="arrow-back" />
</Button>
</Left>
<Body>
<Title>Detail Container</Title>
</Body>
<Right />
</Header>
<Content padder>
<Card>
<CardItem>
<Body>
<Text>Detail Container</Text>
</Body>
</CardItem>
</Card>
</Content>
</Container>
);
};
export default DetailScreen;
this is HomeScreen
import React from "react";
import { StyleSheet, StatusBar } from "react-native";
import { STYLES } from "../../styles/Styles";
import {
Container,
Header,
Title,
Left,
Icon,
Right,
Button,
Body,
Content,
Text,
Card,
CardItem
} from "native-base";
const Home = props => {
closeDrawer = () => {
this.drawer._root.close();
};
openDrawer = () => {
this.drawer._root.open();
};
return (
<Container>
<Header style={STYLES.bgAzulPatios}>
<Left>
<Button transparent onPress={() => props.navigation.openDrawer()}>
<Icon name="menu" />
</Button>
</Left>
<Body>
<Title>HomeScreen</Title>
</Body>
<Right />
</Header>
<Content padder>
<Card>
<CardItem>
<Body>
<Text> Home</Text>
<Button
style={STYLES.bgAzulPatios}
iconLeft
onPress={() => props.navigation.push("ContainerDetail")}
>
<Icon name="arrow-forward" />
<Text>Container Detail</Text>
</Button>
</Body>
</CardItem>
</Card>
</Content>
</Container>
);
};
export default Home;
app.js
.
.
.
render() {
return (
<UserNavigation />
);
}
}
The mistake you are doing here is Login is a different stack and you should not add your detailed screen as a part of Login
Reason: You are making Login as different stack so that when user logs in and even if he presses back button as we came to different stack there is no page behind so the app closes without going to Login Page. So here if you add Detailed Page as a part of login stack it doesnot work
Solution: For Home create another homeStackRoutingComponent with pages like home, detailed and add that as a screen for home
Ex: Home: {
screen: homeStackComponent
}
Here homeStackComponent contains a Stack Container with home, detailed routes with initial route as home :)

Resources