Bottom Navigation | React Native - react-native

I use react-native-paper to implement Bottom Navigation.
I have a BottomNav element. It is located on the main page of the application - Feed Page. When I click on the icon in BottomNav to go to the MapScreen page nothing happens. Help solve the problem.
BottomNav
import React from "react";
import { StyleSheet } from "react-native";
import { BottomNavigation } from "react-native-paper";
import { MapScreen } from "../screens/";
export default class BottomNav extends React.Component {
state = {
index: 0,
routes: [
{ key: "Feed", title: "Feed", icon: "photo-album", color: "#6200ee" },
{ key: "MapScene", title: "MapScene", icon: "inbox", color: "#2962ff" }
]
};
render() {
return (
<BottomNavigation
style={styles.BottomNav}
navigationState={this.state}
onIndexChange={index => this.setState({ index })}
renderScene={BottomNavigation.SceneMap({
Feed: MapScreen,
MapScene: MapScreen
})}
/>
);
}
}
MapScreen
import React from "react";
import { View, Text, StyleSheet } from "react-native";
import { HeaderProfile } from "../uikit/";
export default class MapScreen extends React.Component {
constructor(props) {
super(props);
this.state = {
active: "bookmark-border"
};
}
render() {
return (
<View style={styles.MapScreen}>
<View style={styles.Header}>
<HeaderProfile />
</View>
<Text> Text </Text>
</View>
);
}
}
const styles = StyleSheet.create({
MapScreen: {
backgroundColor: "#1f1f1f",
height: "100%",
flex: 1,
width: "100%"
},
Header: {
marginTop: 24
}
});
export { MapScreen };

Related

How to display the menu list from API in DrawerNavigator

I have created the side menu using DrawerNavigator with the static menu names and screens. I want the menu names and screens to be dynamic. Meaning to say I like to fetch those details in API and display in the DrawerNavigator. Please help to resolve this.
const MyApp = createDrawerNavigator({
HomeScreen: {
screen: HomeScreen,
},
WebMenuScreen: {
screen: WebMenuScreen,
},
}, {
drawerPosition: 'right',
},{
contentComponent: CustomDrawerComponent
}, {
initialRouteName: 'Login'
});
Try this, I hope this will helps you.
in Route File
import DrawerNavigator from "./DrawerNavigator";
import Home from './Home';
import About from './About'
import {
createStackNavigator,
createAppContainer,
} from "react-navigation";
const MainNavigator = createStackNavigator({
DrawerNavigator: {
screen: DrawerNavigator,
navigationOptions: {
header: null
}
},
Home: {
screen: Home,
navigationOptions: {
htitle: 'Home'
}
},
About: {
screen: About,
navigationOptions: {
htitle: 'About'
}
},
});
const Routes = createAppContainer(MainNavigator);
export default Routes;
in DrawerNavigator File
import React from 'react';
import { Platform, Dimensions } from 'react-native';
import { createDrawerNavigator, createAppContainer } from 'react-navigation';
import Home from './Home';
import About from '/About'
import MenuDrawer from './MenuDrawer';
const WIDTH = Dimensions.get('window').width;
const DrawerConfig = {
drawerWidth: WIDTH*0.83,
contentComponent: ({ navigation }) => {
return(<MenuDrawer navigation={navigation} />)
}
}
const DrawerNavigator = createDrawerNavigator(
{
Home:{
screen:Home
},
About:{
screen:About
},
},
DrawerConfig
);
export default createAppContainer(DrawerNavigator);
in Menu Drawer File
import React from "react";
import {
View,
Text,
ScrollView,
Image,
TouchableOpacity,
} from "react-native";
var obj = JSON.parse('{ "name":"Home","name":"About" }');
// import styles from './menuDrawerStyles'
class MenuDrawer extends React.Component {
navLink(nav, text) {
return (
<TouchableOpacity
style={{ height: 50 }}
onPress={() => this.props.navigation.navigate(nav)}
>
<Text style={styles.link}>{text}</Text>
</TouchableOpacity>
);
}
render() {
return (
<View style={styles.container}>
<ScrollView style={styles.scroller}>
{
this.obj.map((data) => {
<View style={styles.bottomLinks}>
<View style={{ flex: 2, flexDirection: "row" }}>
{this.navLink(data.name, data.name)}
</View>
<View style={{ flex: 2, flexDirection: "row" }}>
{this.navLink(data.name, data.name)}
</View>
</View>
})
}
</ScrollView>
</View>
);
}
}
in Menu Button File
import React from "react";
import { StyleSheet , Platform } from "react-native";
import Icon from "react-native-vector-icons/MaterialIcons";
export default class MenuButton extends React.Component {
render() {
return (
<Icon
name="reorder"
color="black"
size={25}
style={styles.menuIcon}
onPress={() => this.props.navigation.toggleDrawer()}
/>
);
}
}
const styles = StyleSheet.create({
menuIcon: {
zIndex: 9,
position: "absolute",
top: Platform.OS === "android" ? 15 : 25,
left: 20
}
});
In Menu Drawer file you can call Api and fetch menu list.

Error: undefined is not an object (evaluating 'this.props.navigation.navigate')

I have created a separate route file and when I am trying to navigate between screens with the help of these routes with react-navigation using stackNavigator I am getting this error I have already tried other solutions available on Stack overflow but none of the answers solve my problem here is my code.
This is my Route.js file
import { createAppContainer, createStackNavigator } from 'react-navigation';
import Login from './screens/Login';
import Register from './screens/Register';
import Start from './screens/Start';
const AppNavigator = createStackNavigator({
Home: {
screen: Start,
},
LoginScreen: {
screen: Login,
},
RegisterScreen: {
screen: Register,
},
}, {
initialRouteName: 'Home',
navigationOptions: {
header: null
}
});
export default createAppContainer(AppNavigator);
And this is my component where I am trying to navigate
import React,{ Component } from 'react';
import { StyleSheet, View, KeyboardAvoidingView,Text } from 'react-native';
import NewButtons from './NewButtons';
import Logo from './Logo';
export default class Start extends Component{
constructor () {
super();
}
loginPress = () => {
this.props.navigation.navigate('LoginScreen');
}
registerPress = () => {
this.props.navigation.navigate('RegisterScreen');
}
render(){
return(
<KeyboardAvoidingView behavior='padding' style={styles.wrapper}>
<View style={styles.logoContainer}>
<Logo/>
<Text style={styles.mainHead}>Welcome to Food Zone</Text>
<Text style={{margin: 10, textAlign:'center'}}>Check out our menus, order food and make reservations{"\n"}{"\n"}</Text>
<NewButtons text="Login"
onPress={this.loginPress}/>
<NewButtons text="Register"
onPress={this.registerPress}/>
</View>
</KeyboardAvoidingView>
);
}
}
const styles = StyleSheet.create({
logoContainer: {
alignItems: 'center',
},
mainHead: {
fontFamily: 'PatuaOne',
color: '#ff9900',
fontSize: 28,
marginTop: -50,
},
})
And this in my button component
import React,{ Component } from 'react';
import { StyleSheet, View,Dimensions } from 'react-native';
import { Button, Text } from 'native-base';
const {width:WIDTH} = Dimensions.get('window')
export default class NewButtons extends Component{
constructor(props){
super(props);
}
handlePress = () => {
this.props.onPress();
}
render(){
return(
<View style={styles.ButtonContainer}>
<Button light style={styles.mainButtons} onPress={this.handlePress()}>
<Text style={styles.textProps}>{this.props.text}</Text>
</Button>
</View>
);
}
}
const styles = StyleSheet.create({
textProps:{
fontFamily: 'PatuaOne',
color: '#ffffff',
},
mainButtons: {
backgroundColor: "#ff9900",
width: 250,
margin: 5,
color: '#ffffff',
justifyContent: 'center',
width: WIDTH -75,
borderRadius: 10,
},
ButtonContainer: {
alignItems: 'center',
}
})
I managed to remove this error by importing routes in App.js file and by calling it in index.js here is my code of App.js file.
import React, {Component} from "react";
import Routes from "./Routes";
const App = () => <Routes/>
export default App;

Header not showing with createBottomTabNavigator - React NAtive

I am creating a very simple tab navigation with two screens. I want to show a header on top of each screen. I am running the following code, but I don't see any header. The header just does not appear.
I am using react-navigation#3.11.1, I tried reverting back to 3.10.0 and even 3.0.0 and still don't see the headers. So I am assuming it's not a bug in react-navigation.
Update: This is the expected behavior. See: https://github.com/react-navigation/react-navigation/issues/6149
import React, {Component} from 'react';
import { View, Text } from 'react-native';
import { createAppContainer, createBottomTabNavigator } from 'react-navigation';
class MusicScreen extends Component {
static navigationOptions = {
title: 'Musiiic',
};
render() {
return (
<View >
<Text>Music Screen</Text>
</View>
);
}
}
class MoviesScreen extends Component {
static navigationOptions = {
headerTitle: 'Movies',
};
render() {
return (
<View>
<Text>Movies Screen</Text>
</View>
);
}
}
const MainNavigation = createBottomTabNavigator({
Music : {
screen: MusicScreen,
navigationOptions: ({navigation}) => ({
title: 'Music',
headerTitle: <Text>MUSIICCCC</Text>,
})
},
Movies : {
screen: MoviesScreen,
navigationOptions: {
title: 'Movies',
},
},
},
{
headerMode: 'screen',
navigationOptions: {
headerVisible: true,
},
}
);
export default createAppContainer(MainNavigation);
Can you try like the following?
eg:
...
...
class MusicScreen extends Component {
static navigationOptions = {
title: 'MUSIICCCC',
headerStyle: {
backgroundColor: '#f4511e',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold',
},
};
render() {
return (
<View >
<Text>Music Screen</Text>
</View>
);
}
}
...
...
const MainNavigation = createBottomTabNavigator({
Music : MusicScreen,
Movies MoviesScreen,
},
{
initialRouteName: 'Music',
}
);
export default createAppContainer(MainNavigation);
Try cleaning up your createBottomTabNavigator like so by removing any header data.
const MainNavigation = createBottomTabNavigator({
Music : {screen: MusicScreen},
Movies : {screen: MoviesScreen},
}
);
Add navigationOptions to each screen individually.
class MusicScreen extends Component {
static navigationOptions = {
title: 'Musiiic',
};
render() {
return (
<View >
<Text>Music Screen</Text>
</View>
);
}
}
class MoviesScreen extends Component {
static navigationOptions = {
title: 'Movies',
};
render() {
return (
<View>
<Text>Movies Screen</Text>
</View>
);
}
}
Here are some docs [https://reactnavigation.org/docs/en/headers.html]
Could you try this?
import React, {Component} from 'react';
import { View, Text } from 'react-native';
import { createAppContainer, createBottomTabNavigator } from 'react-navigation';
class MusicScreen extends Component {
render() {
return (
<View >
<Text>Music Screen</Text>
</View>
);
}
}
class MoviesScreen extends Component {
render() {
return (
<View>
<Text>Movies Screen</Text>
</View>
);
}
}
const MainNavigation = createBottomTabNavigator({
Music : {
screen: MusicScreen,
navigationOptions: {
title: "Music"
}
},
Movies : {
screen: MoviesScreen,
navigationOptions: {
title: 'Movies',
},
},
},
{
headerMode: 'screen'
}
);
export default createAppContainer(MainNavigation);

ImageBackground component as a container of react-navigation router hiding all child components

I want to set a background image to all of the screens in my react native application,
I am using ImageBackground component on the top level of my components tree like that:
export default class App extends React.Component {
render(){
return(
<View style={{ flex: 1 }}>
<ImageBackground source={require('../assets/app-bg.png')} style={{width: '100%', height: '100%', flex: 1, zIndex: 0, resizeMode: 'cover' }}>
<Router />
</ImageBackground>
</View>)
}
}
and I have the child component which is the router from react-navigation
like that:
class LandingPage extends React.Component {
render(){
return(
<View style={{flex: 1, zIndex: 999}}>
<Text>here is landing page></Text>
</View>
)
}
}
const RouterNavigator = createAppContainer(createStackNavigator({
Landing: {
screen: Landing,
navigationOptions:{
header: null
}
}
}
export default class Router extends React.Component {
render() {
return <RouterNavigator style={{flex: 1}}/>
}
}
the problem is that the background image is being rendered but the child component LandingPage is being hidden even though it is being rendered too!
Just have a look at this example.Does this help you acheive what you were
trying to.
import * as React from 'react';
import { Text, View, StyleSheet, ImageBackground } from 'react-native';
import { Constants } from 'expo';
import AssetExample from './components/AssetExample';
import { createAppContainer, createStackNavigator } from 'react-navigation';
import { Card } from 'react-native-paper';
class LandingPage extends React.Component {
render() {
return (
<View>
<Text>here is landing page</Text>
</View>
);
}
}
const RouterNavigator = createAppContainer(
createStackNavigator(
{
LandingPage: {
screen: LandingPage,
navigationOptions: {
header: null,
},
},
},
{
mode: 'card',
transparentCard: true,
cardStyle: { backgroundColor: 'transparent' },
transitionConfig: () => ({
containerStyle: {
backgroundColor: 'transparent',
},
}),
initialRouteName: 'LandingPage',
}
)
);
export default class App extends React.Component {
render() {
return (
<ImageBackground
source={require('./bgimage.jpeg')}
style={{
flex: 1,
}}>
<RouterNavigator />
</ImageBackground>
);
}
}

createBottomTabNavigator: how do I reload/refresh a tab screen on tab on the tab-icon?

So I have a TabNavigator with 3 screens.
import React from 'react';
import {TabNavigator,createBottomTabNavigator } from 'react-navigation';
import ActivateScannerPage from '../pages/ActivateScannerPage';
import ScanTicketPage from '../pages/ScanTicketPage';
import HomePage from '../pages/HomePage';
import SwipeList from '../components/SwipeList';
import FontAwesome, { Icons } from 'react-native-fontawesome';
import { Icon } from 'react-native-elements';
export default createBottomTabNavigator (
{
HomeScreen:{
screen:HomePage,
navigationOptions: {
tabBarIcon:()=>
<Icon
name='home'
type='font-awesome'
color='#5bc0de'/>
},
},
AcitvateScannerPage:{
screen:ActivateScannerPage,
navigationOptions: {
tabBarIcon:()=> <Icon
name='qrcode'
type='font-awesome'
color='#5bc0de'/>
},
},
ScanTicketPage:{
screen:ScanTicketPage,
navigationOptions: {
tabBarIcon:()=> <Icon
name='ticket'
type='font-awesome'
color='#5bc0de'/>
},
},
},
{
tabBarOptions: {
activeTintColor: '#5bc0de',
inactiveTintColor :'white',
labelStyle: {
fontSize: 12,
},
style: {
backgroundColor: '#444444'
},
}
}
);
When I click on ActivateScannerPage there will be opened the camera for scanning a QR Code.
import React, { Component } from 'react';
import {
StyleSheet,
View,
} from 'react-native';
import QrCode from '../components/QrCode';
class ActivateScannerPage extends Component {
static navigationOptions = {
title: 'Aktivierung Scanner',
};
constructor (props){
super(props);
}
render(){
return(
<View style={styles.viewContent}>
<QrCode scanner={true} headerText="Aktivieren Sie Ihren Scanner"/>
</View>
);
}
}
const styles = StyleSheet.create({
viewContent:{
flex:1
}
});
export default ActivateScannerPage;
So my problem ist when the app starts and I click on the tab "ActivateScannerPage/Aktivierung Scanner" then it opens the camera and I can scan my codes without a problem. But when I tab to another tabScreen, e.g. back to the home screen and then go back to the AcitivateScannerPage, the view is not refreshed or rendered new. So the camera dont open anymore and I see a black screen.
Is there a way to fix this? Can I reload or rerender the screen by tapping on the tabIcon?
Thanks.
EDIT:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
AsyncStorage,
} from 'react-native';
import QRCodeScanner from 'react-native-qrcode-scanner';
import moment from 'moment';
import { Icon } from 'react-native-elements';
class QrCode extends Component {
static navigationOptions=(props)=>({
title: `${props.navigation.state.params.scannerName}`,
headerTintColor: 'white',
headerStyle: {backgroundColor: '#444444'},
headerTitleStyle: { color: 'white' },
})
constructor(props){
super(props);
this.state={
.....some states.....
}
}
onSuccess(e) {
..... do something..... here I get my data which I use
}
fetchDataScanner(dataMacroID,requestKey,hash) {
......
}
fetchDataTicketCheck(dataMacroID,requestKey,ticketValue){
.....
}
fetchDataTicketValidate(dataMacroID,requestKey,dataMicroID,ticketValue){
.....
}
saveDataScannerActivation=()=>{
.....
}
render() {
return (
<View style={styles.viewContent}>
<View style={{flex:4}}>
<QRCodeScanner
reactivateTimeout={2000}
reactivate={true}
onRead={this.onSuccess.bind(this)}
/>
</View>
</View>
);
}
}
......
export default QrCode;
in screens you designed for your tabs have to do flowing steps:
1: import withNavigationFocus from react-navigation to your class .
2: then export your like this : export default withNavigationFocus(yourclassname)
3: use this code to update or manage your state
shouldComponentUpdate = (nextProps, nextState) => {
if (nextProps.isFocused) {
...
return true;
} else {
...
return false;
}
};
With react-navigation you can detect whenever the ActivateScannerPage is active/tapped.
Add this code in componentDidMount in ActivateScannerPage
this.subs = [
this.props.navigation.addListener('didFocus', () => this.isFocused()),
];
And remove the listener if ActivateScannerPage will unmount
componentWillUnmount() {
this.subs.forEach(sub => sub.remove());
}