How do i navigate between screens in my shopping app? - react-native

'm new to react-native and mobile application. I'm trying to build a basic shopping app.i have the sports options such as cricket,football,tennis and whenever the cricket button is pressed, the cricket products must be displayed and i can follow it up for the other two products
i tried using stack navigator to navigate between screens but i seem to get a error . i tried using createstacknavigator but it doesnt come out right
1.App.js
import React, { Component } from 'react';
import { Text, View } from 'react-native';
import { StackNavigator } from 'react-navigation'
import FirstScreen from './src/FirstScreen'
import SecondScreen from './src/cricket'
const Navigation = StackNavigator({
First: {screen: FirstScreen},
Second: {screen: SecondScreen}
});
export default Navigation
AppRegistry.registerComponent('AwesomeProject', () => Navigation);
2.FirstScreen.js
import React, { Component } from 'react';
import { Alert, AppRegistry, Image, Platform, StyleSheet, Text,
TouchableHighlight, TouchableOpacity, TouchableNativeFeedback,
TouchableWithoutFeedback, View } from 'react-native';
import { StackNavigator } from 'react-navigation'
export default class FirstScreen extends Component {
//_onPressButton() {
// Alert.alert('You tapped the button!')
//}
//_onLongPressButton() {
//Alert.alert('You long-pressed the button!')
//}
static navigationOptions = {
title: 'First Screen',
};
render() {
return (
<View style={styles.container}>
<TouchableOpacity onPress={this._onPressButton}>
<View style={styles.button}>
<Text style={styles.buttonText}>Cricket</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={this._onPressButton}>
<View style={styles.button}>
<Text style={styles.buttonText}>Football</Text>
</View>
</TouchableOpacity>
<TouchableOpacity onPress={this._onPressButton}>
<View style={styles.button}>
<Text style={styles.buttonText}>Tennis</Text>
</View>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
paddingTop: 60,
alignItems: 'center'
},
button: {
marginBottom: 30,
width: 260,
alignItems: 'center',
backgroundColor: '#2196F3'
},
buttonText: {
padding: 20,
color: 'white'
}
});
// skip this line if using Create React Native App
//AppRegistry.registerComponent('AwesomeProject', () => Touchables);
3.Cricket.js
import React, { Component } from 'react';
import {Alert, Button, ScrollView, StyleSheet, AppRegistry, Text, View
} from 'react-native';
const styles = StyleSheet.create({
rowContainer: {
flex: 1,
height: 75,
width: '100%',
flexDirection: 'row', // children will be on the same line
justifyContent: 'space-between',
alignItems: 'center',
margin: 10,
},
buttonContainer: {
flex: 1,
},
text: {
flex: 2, // Text takes twice more space as button container
color: 'red',
fontWeight: 'bold',
fontSize: 20,
},
});
class Greeting extends Component {
static navigationOptions = {
title: 'Second Screen',
};
_onPressButton() {
Alert.alert('Sorry you have no credit!')
}
render() {
return (
<View style={styles.rowContainer}>
<Text style={styles.text}>{this.props.name}</Text>
<View style={styles.buttonContainer}>
<Button
onPress={this._onPressButton}
title="BUY"
/>
</View>
</View>
);
}
}
export default class SecondScreen extends Component {
render() {
return (
<ScrollView>
<View style={{alignItems: 'flex-start', top: 0, flex: 2,
backgroundColor: 'black'}}>
<Greeting name='Shoe- 800' />
<Greeting name='Jersey - 350' />
<Greeting name='Stockings - 100' />
<Greeting name='Cones - 50' />
<Greeting name='Whistle - 80' />
<Greeting name='Helmet - 750' />
<Greeting name='Tennis Ball-6 pack - 800' />
<Greeting name='Nets - 1500' />
<Greeting name='Leg Pads - 1000' />
<Greeting name='Stumps - 800' />
<Greeting name='Gloves - 600' />
</View>
</ScrollView>
);
}
}
When the cricket button is pressed, the screen should navigate to the list of cricketproducts which is the (cricket.js)

As you are using react-navigation, you just need to use the navigation prop. You have commented the part where you handle the press. Just change that function to actually navigate to the screen you want:
_onPressButton=()=>{
this.props.navigation.navigate("Second")
}
If you are not using arrow functions, you need to bind the function to have access to the this of that screen. To do that you need to add inside your constructor:
constructor(props){
super(props)
this._onPressButton.bind(this)
}
after that you can call it by doing:
_onPressButton() {
this.props.navigation.navigate("Second")
}
As you are using a stackNavigator, you have different ways to navigate to the other screen of the same stack. You have different ways to navigate. For example:
this.props.navigation.push("Second")
This method pushes a new screen to the stack, no matter what screen it is
this.props.navigation.navigate("Second")
Navigates to a new screen in the stack, will push it in the stack only if the screen hasn't been focussed before
this.props.navigation.replace("Second")
This will navigate to a new screen without pushing it to the stack, "replacing" the screen you was watching with the new one.
EDIT.
For the error you stated in the comment, it's because there's not an app container. To do so, just do:
import { createStackNavigator, createAppContainer } from 'react-navigation'
Then do
const Navigation = createAppContainer(createStackNavigator({
First: {screen: FirstScreen},
Second: {screen: SecondScreen}
}));

Use the Move Screen command.
this.props.navigation.navigate("Second")

Related

Unable to navigate using reusable card components in React Native

I have this HomeScreen file, in it I have added Card component(Dashboard & Highlights), I have Customized the Card Components with the TitleCard to reuse the styling,
In each card there is "View All" Button to navigate to its individual Screens,
When I don't use the Cards and put the entire code in home screen and Click on the View All Button on home screen then it navigates to that page, but when I use the Cards and use its props to navigate to the link provided as forwardLink props then
I get this error
"ReferenceError: Can't find variable: navigation"
Also when I add this.props.navigation.navigate('{props.forwardLink}') in TitleCard
I get this error message:
TypeError: undefined is not an object (evaluating '_this.props.navigation')
Here are the codes for each file
TitleCards
import React from 'react';
import {StyleSheet, Text, View, TouchableOpacity} from 'react-native';
const TitleCards = props => {
return (<View style={styles.textTitlesContainer}>
<Text style={styles.textTitle}>{props.leftTitle}</Text>
<TouchableOpacity
onPress={() => navigation.navigate('{props.forwardLink}')}>
<Text style={[styles.textTitle, {color: '#F483A7'}]}>
{props.rightTitle}
</Text>
</TouchableOpacity>
</View>)
};
const styles = StyleSheet.create({
textTitlesContainer: {
flex: 1,
width: '100%',
flexDirection: 'row',
justifyContent: 'space-between',
padding: 5,
},
textTitle: {
fontSize: 20,
fontWeight: '800',
color: '#fff',
},
});
export default TitleCards;
HomeScreen
import React, {Component} from 'react';
import {
SafeAreaView,
ScrollView,
StyleSheet,
} from 'react-native';
import {CustomHeader} from '../index';
import Colors from '../constants/Colors';
import DashboardCard from './DashboardCard';
import HighlightCard from './HighlightCard';
export class HomeScreen extends Component {
render() {
return (
<SafeAreaView style={{flex: 0, backgroundColor: Colors.primary}}>
<CustomHeader
title="Home"
isHome={true}
navigation={this.props.navigation}
/>
<ScrollView style={styles.container}>
<DashboardCard />
<HighlightCard />
</ScrollView>
</SafeAreaView>
);
}
}
const styles = StyleSheet.create({
container: {
height:900, backgroundColor: Colors.mainBackground,
paddingTop:6,
},
});
export default HomeScreen;
HighlightCard
import React, {Component} from 'react';
import {Text, View} from 'react-native';
import {CustomHeader} from '../../index';
const HighlightCard = (prop) => {
return (
<Card>
<TitleCards leftTitle="Highlights" rightTitle="View More" forwardLink="Highlights">
</TitleCards>
<View>
<Text>News Feed</Text>
</View>
</Card>
);
};
export default HighlightCard;
const styles = StyleSheet.create({
textTitle: {
fontSize: 20,
fontWeight: '800',
color: '#fff',
},
});
When I use the HighlightCard codes directly in HomeScreen then it navigates to that page, below is that code which works if I use it directly in Home Screen
*{/* <Text style={styles.textTitle}>Highlights</Text>
<TouchableOpacity
onPress={() => this.props.navigation.navigate('Highlights')}>
<Text style={[styles.textTitle, {color: '#F483A7'}]}>View All</Text>
</TouchableOpacity> */}*
I think there is something wrong I am doing is using the props or referencing to the navigation page
I also tried creating a const for navigation
const {navigate} = this.props.navigation
this didn't worked either

Cannot read property 'navigation' of undefined Evaluating App.js Loading App.js

Looking to have button enter go into another screen:
need help with navigation screen.
I keep getting error:
Cannot read property 'navigation' of undefined
Evaluating App.js
Loading App.js
TypeError: Cannot read property 'navigation' of undefined
https://snack.expo.io/#ganiyat1/colorful-thrills
import * as React from 'react';
import { Text, View, StyleSheet, ImageBackground, Image, Button } from 'react-native';
import Constants from 'expo-constants';
import { StackNavigator} from 'react-navigation';
import Books from './components/Books';
// You can import from local files
// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';
const Book = StackNavigator({
Books: { screen: Books },
});
const { navigate } = this.props.navigation;
export default function App() {
return (
<View style={styles.container}>
<View style={styles.topContainer}>
<Text style={styles.title}> Colorful Thrills
</Text >
</View>
<View style={styles.bottomContainer}></View>
<View style={styles.imageContainer}>
<Image
style={styles.image}
source={require('./assets/bookcover.png')}
/>
<Text style={styles.paragraph}>
{"\n"} BOOKWORMS, UNITE! {"\n"} {"\n"}
Suspense, Mystery and Thrillers by Authors of Color
</Text>
<Button
color='#ff914d'
title= 'ENTER'
onPress={() =>
navigate('Books')}
/>
</View>
</View>
);
}
In the above code snippet, I don't see a default Navigator being returned form the entry file, which is App.js by default in React Native.
I assume that you just started to learn React Native, so I will spare you all the minor details and walk you through the solution.
I refactored the App.js file to a into a new component file in /components/Home.js.
Added a default stack Navigator in App.js which has two screens, Home and Books.
Now you can access all the Navigation props in your Home and Books component, as it is being declared in the Navigator variable in App.js
Here is a live demo of your code on Expo.
//App.js
import * as React from 'react';
import { Text, View, StyleSheet, ImageBackground, Image, Button } from 'react-native';
import Constants from 'expo-constants';
import { StackNavigator} from 'react-navigation';
import Books from './components/Books';
import Home from './components/Home'
import { Card } from 'react-native-paper';
const Navigator = StackNavigator({
Books: { screen: Books },
Home:{screen:Home}
});
export default function App(props) {
return (
<Navigator />
);
}
//component/Books.js
import React, { useState } from 'react';
import { StyleSheet, SafeAreaView,Button } from 'react-native';
import MaterialTabs from 'react-native-material-tabs';
const Books = (props) => {
const {navigation} = props
const [selectedTab, setSelectedTab] = useState(0);
return (
<SafeAreaView style={styles.container}>
<MaterialTabs
items={['New Releases', 'All', 'BOM']}
selectedIndex={selectedTab}
onChange={setSelectedTab}
barColor="#1fbcd2"
indicatorColor="#ff914d"
activeTextColor="white"
/>
<Button
color='#ff914d'
title= 'Home'
onPress={() =>
navigation.navigate('Home')}
/>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
});
export default Books
//component/Home.js
import React from 'react'
import {View,Text,StyleSheet,Button,Image} from 'react-native'
const Home = (props) => {
const {navigation} = props
return (
<View style={styles.container}>
<View style={styles.topContainer}>
<Text style={styles.title}> Colorful Thrills
</Text >
</View>
<View style={styles.bottomContainer}></View>
<View style={styles.imageContainer}>
<Image
style={styles.image}
source={require('../assets/bookcover.png')}
/>
<Text style={styles.paragraph}>
{"\n"} BOOKWORMS, UNITE! {"\n"} {"\n"}
Suspense, Mystery and Thrillers by Authors of Color
</Text>
<Button
color='#ff914d'
title= 'ENTER'
onPress={() =>
navigation.navigate('Books')}
/>
</View>
</View>
)
}
export default Home
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
},
topContainer: {
flex: 1,
backgroundColor: '#ff914d',
},
bottomContainer: {
flex: 1,
backgroundColor: '#96d0e3',
},
imageContainer: {
position: 'absolute',
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
},
image: {
width: 300,
},
title:{
margin: 24,
marginTop: 50,
fontSize: 40,
fontWeight: 'bold',
textAlign: 'center',
fontFamily: 'GillSans-Italic',
},
paragraph: {
margin: 24,
marginTop: 0,
fontSize: 20,
fontWeight: 'bold',
textAlign: 'center',
}
});

How can I get button-click-navigation and touch-slide-navigation at the same time in React Native?

This is some part of the YouTube video.(using createStackNavigator in React Native).
How can I achieve this kind of effect in React Native( Navigation by button click and touch slide at the same time ) ?
I followed this video but it works such as fadeIn, fadeOut effect in jQuery.
The author of this video installed "yarn add react-navigation#2.0.0-beta.3".
I installed it but it gave me error. So I used this. "yarn add react-navigation".
This is the whole code of App.js.
import React from 'react';
import { Button, View, Text } from 'react-native';
import { createAppContainer } from "react-navigation";
import { createStackNavigator } from 'react-navigation-stack';
class ScreenComponentOne extends React.Component {
render() {
return (
<View
style={{
flex: 1,
alignItems: "center",
justifyContent: "center",
borderWidth: 25,
borderColor: '#f00',
}}
>
<Button
title="Go to the screen two"
onPress={() => {
this.props.navigation.navigate('RouteNameTwo')
}}
/>
</View>
)
}
}
class ScreenComponentTwo extends React.Component {
render() {
return (
<View
style={{
flex: 1,
alignItems: "center",
justifyContent: "center",
borderWidth: 25,
borderColor: '#f0f',
}}
>
<Button
title="Go to the screen one"
onPress={() => {
this.props.navigation.navigate({routeName:'RouteNameOne', transitionStyle: 'inverted'})
}}
/>
</View>
)
}
}
const AppNavigator = createStackNavigator({
RouteNameOne: {
screen:ScreenComponentOne,
navigationOptions:{
header:null,
}
},
RouteNameTwo: {
screen:ScreenComponentTwo,
navigationOptions:{
header:null,
}
},
},
{
initialRouteName:"RouteNameOne"
});
const AppContainer = createAppContainer(AppNavigator);
export default class App extends React.Component {
render() {
return <AppContainer />;
}
}
I'd like to get touch-slide-navigation and button-click-navigation at the same time.
The module that I installed is as follows:
-yarn install
-yarn add react-navigation (for createAppContainer)
-yarn add react-navigation-stack (for createStackNavigator)
How can I achieve this ?

React native layout misbehaving

I am trying to learn React native with Ignite. Been fighting with the layout.
Here is my main container render function:
render () {
return (
<View style={styles.mainContainer}>
<Image source={Images.background} style={styles.backgroundImage} resizeMode='stretch' />
<View style={[styles.container]}>
<View style={styles.section} >
{/* <Image source={Images.ready} />*/}
<Text style={styles.sectionText}>
Tap to randomly choose your training task. Slack off for 5
</Text>
</View>
<View style={styles.centered}>
<TouchableOpacity onPress={this._onPressButton}>
<Image source={Images.launch} style={styles.logo} />
</TouchableOpacity>
</View>
</View>
<View style={[styles.bottom]}>
<View >
<BottomBar />
</View>
</View>
</View>
)
}
In particular, the last sibling of the container has a view with a BottomBar component.The bottom style does this:
bottom: {
justifyContent: 'flex-end',
marginBottom: Metrics.baseMargin
}
the BottomBar component:
import React, { Component } from 'react'
// import PropTypes from 'prop-types';
import { View, Text, TouchableOpacity } from 'react-native'
import styles from './Styles/BottomBarStyle'
import Icon from 'react-native-vector-icons/FontAwesome'
export default class BottomBar extends Component {
// // Prop type warnings
// static propTypes = {
// someProperty: PropTypes.object,
// someSetting: PropTypes.bool.isRequired,
// }
//
// // Defaults for props
// static defaultProps = {
// someSetting: false
// }
render () {
console.tron.log('rendering my component')
console.tron.log('Bottom bar styles: \n',styles)
return (
<View style={[styles.iconsContainer, styles.debugGreen]}>
<TouchableOpacity style={[styles.icons,styles.debugYellow]} onPress={()=>{console.tron.log('rocket')}} >
<Icon style={styles.icons} name='rocket' size={40} color='white' />
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={ ()=>{console.tron.log('send')} }>
<Icon style={styles.icons} name='send' size={40} color='white' />
</TouchableOpacity>
</View>
)
}
}
the styles associated with it:
import { StyleSheet } from 'react-native'
import DebugStyles from '../../Themes/DebugStyles'
import { Metrics } from '../../Themes/'
export default StyleSheet.create({
...DebugStyles,
iconsContainer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
height: 45,
borderRadius: 5,
marginHorizontal: Metrics.section,
marginVertical: Metrics.baseMargin
},
icons:{
height: 45
}
})
The issue I have, is that if I saw that bottomBar component for a Rounded button as such:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { TouchableOpacity, Text } from 'react-native'
import styles from './Styles/RoundedButtonStyles'
import ExamplesRegistry from '../Services/ExamplesRegistry'
// Note that this file (App/Components/RoundedButton) needs to be
// imported in your app somewhere, otherwise your component won't be
// compiled and added to the examples dev screen.
// Ignore in coverage report
/* istanbul ignore next */
ExamplesRegistry.addComponentExample('Rounded Button', () =>
<RoundedButton
text='real buttons have curves'
onPress={() => window.alert('Rounded Button Pressed!')}
/>
)
console.tron.log('Rounded button style: ',styles)
export default class RoundedButton extends Component {
static propTypes = {
onPress: PropTypes.func,
text: PropTypes.string,
children: PropTypes.string,
navigator: PropTypes.object
}
getText () {
const buttonText = this.props.text || this.props.children || ''
return buttonText.toUpperCase()
}
render () {
console.tron.log('roundedButton styles:', styles)
return (
<TouchableOpacity style={styles.button} onPress={this.props.onPress}>
<Text style={styles.buttonText}>{this.getText()}</Text>
</TouchableOpacity>
)
}
}
with its styles:
import { StyleSheet } from 'react-native'
import { Fonts, Colors, Metrics } from '../../Themes/'
export default StyleSheet.create({
button: {
height: 45,
borderRadius: 5,
marginHorizontal: Metrics.section,
marginVertical: Metrics.baseMargin,
backgroundColor: Colors.fire,
justifyContent: 'center'
},
buttonText: {
color: Colors.snow,
textAlign: 'center',
fontWeight: 'bold',
fontSize: Fonts.size.medium,
marginVertical: Metrics.baseMargin
}
})
I get the expected view :
However, with my BottomBar component I get:
One thing to notice is that the debugGreen style is just a border that should wrap around my BottomBar component and it is shown flat, but the icons within it render lower, and the debugYellow styled box around the icon is shown around the icon as expected, just shifted a whole way down.
If your mainContainer's view is flex : 1 or height : 100%, you should divide the child's height by 8:2 or the flex by 8:2.
Example
<View style={styles.mainContainer}> // flex: 1
<View style={styles.container}> // flex : 0.8
...
</View>
<View style={styles.bottom}> // flex : 0.2
<BottomBar />
</View>
</View>

React Native render and switch with navigator onPress

I've just started to develop with React Native a week ago.
Can anyone help me with simple render and switch onPress to another view?
I've read tones of examples, but most of them are cutted or not well documents as if on FaceBook Doc pages. There was no totally completed example with Nav.
Here is what was done yet - View that should be rendered 1st:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
TextInput,
TouchableHighlight,
TouchableNativeFeedback,
Platform,
Navigator
} from 'react-native';
export default class SignUp extends Component {
buttonClicked() {
console.log('Hi');
this.props.navigator.push({title: 'SignUp', component:SignUp});
}
render() {
var TouchableElement = TouchableHighlight;
if (Platform.OS === ANDROID_PLATFORM) {
TouchableElement = TouchableNativeFeedback;
}
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to Cross-Profi!
</Text>
<Text style={styles.field_row}>
<TextInput style={styles.stdfield} placeholder="Profession" />
</Text>
<Text style={styles.field_row}>
<TextInput style={styles.stdfield} placeholder="E-mail" />
</Text>
<Text style={styles.field_row}>
<TextInput style={styles.stdfield} secureTextEntry={true} placeholder="Password" />
</Text>
<TouchableElement style={styles.button} onPress={this.buttonClicked.bind(this)}>
<View>
<Text style={styles.buttonText}>Register</Text>
</View>
</TouchableElement>
{/* <Image source={require("./img/super_car.png")} style={{width:120,height:100}} />*/}
<Text style={styles.instructions}>
Press Cmd+R to reload,{'\n'}
Cmd+D or shake for dev menu
</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'lightblue',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
color: 'darkred',
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
field_row: {
textAlign: 'center',
color: '#999999',
margin: 3,
},
stdfield: {
backgroundColor: 'darkgray',
height: 50,
width: 220,
textAlign: 'center'
},
button: {
borderColor:'blue',
borderWidth: 2,
margin: 5
},
buttonText: {
fontSize: 18,
fontWeight: 'bold'
}
});
const ANDROID_PLATFORM = 'android';
Navigator class that should render different views:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Platform,
Navigator
} from 'react-native';
var MainActivity = require('./app/MainActivity.js');
var SignUp = require('./app/SignUp.js');
class AwesomeProject extends Component {
/*constructor(props) {
super(props);
this.state = {text: ''};
}*/
render() {
// this.props.navigator.push({title:'SignUp'});
return (
<Navigator initialRoute={{title:'SignUp', component:SignUp}}
configureScene={() => {
return Navigator.SceneConfigs.FloatFromRight;
}}
renderScene={(route, navigator) =>
{
console.log(route, navigator);
if (route.component) {
return React.createElement(route.component, {navigator});
}
}
} />
);
}
}
const ANDROID_PLATFORM = 'android';
const routes = [
{title: 'MainActivity', component: MainActivity},
{title: 'SignUp', component: SignUp},
];
AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);
It doesn't seem to be clear whether there must be require of a class and declaration of class as export default.
There is an error: Element type is invalid: expected a string, ... but got object etc
Help with examples would be great. Thx
In your require call, you should either replace it import statement or use default property of require module i.e:
var MainActivity = require('./app/MainActivity.js').default;
or use
import MainActivity from "./app/MainActivity";
In ES6, require doesn't assign default property of module to variable.
See this blog post for better understanding of require working in es6