Re-render only on button press in react-native - react-native

I have a react native screen where 2 text inputs are added by default, while 2 text inputs are added on button press only.
I am able to add text to the first 2 text inputs, but the other 2 are not accepting text, they accept text only when "Add another car" button is pressed again.
What am I missing? Why is the view not re-rendered when I add text.
CarReg.js
'use strict';
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
TextInput
} from 'react-native';
var Button = require('./Button');
var Parse = require('parse/react-native');
class CarReg extends Component {
constructor(props) {
super(props);
this.state = {
carNumber1: "",
carState1: "",
carNumber2: "",
carState2: "",
errorMessage: "",
carEntry: <View/>,
};
}
render() {
const { page } = this.state;
return (
<View style={styles.container}>
<Text
style={[styles.titleContainer, {marginBottom: 30}]}>
Please register your cars, you can add up-to 2 cars </Text>
<Text style={styles.titleContainer}> License plate number: </Text>
<TextInput
style={styles.textInputContainer}
onChangeText={(text) => this.setState({carNumber1: text})}
value={this.state.carNumber1}/>
<Text style={styles.titleContainer}> State: </Text>
<TextInput
style={styles.textInputContainer}
onChangeText={(text) => this.setState({carState1: text})}
value={this.state.carState1}/>
{this.state.carEntry}
<Text>{this.state.errorMessage}</Text>
<Button text="Add another car" onPress={this.onAddCarPress.bind(this)}/>
<Button text="Submit" onPress={this.onSubmitPress.bind(this)}/>
<Button text="I don't have a car" onPress={this.onNoCarPress.bind(this)}/>
</View>
);
}
onAddCarPress() {
this.setState({carEntry:
<View style={styles.addCarView}>
<Text style={styles.titleContainer}> License plate number: </Text>
<TextInput
style={styles.textInputContainer}
onChangeText={(text) => this.setState({carNumber2: text})}
value={this.state.carNumber2}/>
<Text style={styles.titleContainer}> State: </Text>
<TextInput
style={styles.textInputContainer}
onChangeText={(text) => this.setState({carState2: text})}
value={this.state.carState2}/>
</View>
})
}
onSubmitPress() {
this.props.navigator.push({name: 'main'});
}
onNoCarPress() {
this.props.navigator.push({name: 'main'});
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
addCarView: {
backgroundColor: '#F5FCFF',
justifyContent: 'center',
alignItems: 'center',
},
titleContainer: {
fontSize: 20,
fontFamily: 'Helvetica',
},
textInputContainer: {
padding: 4,
margin: 5,
borderWidth: 1,
borderRadius: 10,
width: 200,
height: 40,
fontFamily: 'Helvetica',
alignSelf: 'center',
marginBottom: 10,
marginTop: 10,
},
});
module.exports = CarReg;
Button.js
'use strict';
import React, { Component } from 'react';
import {
StyleSheet,
Text,
TouchableHighlight,
} from 'react-native';
class Button extends Component {
constructor(props) {
super(props);
}
render() {
return (
<TouchableHighlight
style={styles.container}
onPress={this.props.onPress}
underlayColor ='gray'>
<Text style={styles.textContainer}>{this.props.text}</Text>
</TouchableHighlight>
);
}
}
const styles = StyleSheet.create({
container: {
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
marginTop: 10,
padding: 5,
borderWidth: 1,
borderRadius: 10,
},
textContainer: {
fontFamily: 'Helvetica',
justifyContent: 'center',
alignSelf: 'center',
textAlign: 'center',
flex:1,
fontSize: 20,
}
});
module.exports = Button;

I created the demo of your code on the rnplay. (only ios version.)
I think it's not the good idea to push html to your state. The state is for the data like an array, a boolean and templates (strings). This is only my opinion, of course.
After you click to submit button, look at the console.

Related

Two buttons based on click, function will be called

I want to create a design which I have attached, there are two buttons, when I click on unlimited credit the colour of the button should become red and limited should be white and when I click on limited the limited button should be red and unlimited colour should be white as shown in the image and also when I click on button it should call functions, the function will have some design part and there will be two functions one for unlimited and other for limited based on the button click it should call that function, please let me know how can I execute this.
Final Output:
Full code:
const ButtonContainer = () => {
const [btnOne, setBtnOne] = useState(false);
const [btnTwo, setBtnTwo] = useState(false);
const clickStyle = { backgroundColor: '#F5D9D0', borderColor: '#F3805E' }
return (
<View style={styles.buttonContainer}>
<TouchableOpacity
onPress={() => {
setBtnOne(true);
setBtnTwo(false);
}}
style={[
styles.button,
btnOne ? clickStyle : null,
]}>
<Text>Unlimited Credit</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
setBtnOne(false);
setBtnTwo(true);
}}
style={[
styles.button,
btnTwo ? clickStyle : null,
]}>
<Text>Limited Credit</Text>
</TouchableOpacity>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
buttonContainer: {
flexDirection: 'row',
justifyContent: 'space-evenly',
},
button: {
borderColor: 'grey',
borderWidth: 2,
padding: 10,
borderRadius: 20,
},
});
Live working example: Expo Snack
here's a snack I created: https://snack.expo.io/#yoobit0616/two-buttons
import React, { useState } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { Button } from 'react-native-elements';
import Constants from 'expo-constants';
export default function App() {
const [disabledButton, setDisabledButton] = useState(true);
return (
<View style={styles.container}>
<View style={styles.buttonView}>
<Button
style={styles.button}
onPress={() => setDisabledButton(!disabledButton)}
buttonStyle={
disabledButton
? { backgroundColor: 'white' }
: { backgroundColor: 'red' }
}
titleStyle={{ color: 'black' }}
title="Unlimited Credit"></Button>
<Button
style={styles.button}
onPress={() => setDisabledButton(!disabledButton)}
buttonStyle={
!disabledButton
? { backgroundColor: 'white' }
: { backgroundColor: 'red' }
}
titleStyle={{ color: 'black' }}
title="Limited Credit"></Button>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
buttonView: {
flexDirection: 'row',
justifyContent: 'center',
},
button: {
height: 40,
width: 150,
marginLeft: 20,
borderRadius: 5,
borderWidth: 1,
},
});

Cannot read property 'navigate' of undefined in a .then() => { } with Firebase

Alright. So i'm new to react native and im learning on creating a signup authentication with Firebase. I have three files: Signup.js, Login.js and Profile.js. In my Signup screen when i call on the function handleSignUp onPress i get:
Cannot read property 'navigate' of undefined.
I assume that i need to get out of the function scope to the global scope? I'm not sure what i'm missing here or how to tackle it. any advice?
Here's my code.
{*Signup.js*}
import React from 'react'
import { View, TextInput, StyleSheet, TouchableOpacity, Text } from 'react-native'
import { createAppContainer, createSwitchNavigator } from 'react-navigation'
import { withNavigation } from 'react-navigation';
import Firebase from '../config/Firebase'
class Signup extends React.Component {
state = {
name: '',
email: '',
password: ''
}
handleSignUp = () => {
const { email, password } = this.state
Firebase.auth()
.createUserWithEmailAndPassword(email, password)
.then(()=>this.props.navigation.navigate('Profile'))
.catch(error => console.log(error))
}
render() {
return (
<View style={styles.container}>
<TextInput
style={styles.inputBox}
value={this.state.name}
onChangeText={name => this.setState({ name })}
placeholder='Full Name'
/>
<TextInput
style={styles.inputBox}
value={this.state.email}
onChangeText={email => this.setState({ email })}
placeholder='Email'
autoCapitalize='none'
/>
<TextInput
style={styles.inputBox}
value={this.state.password}
onChangeText={password => this.setState({ password })}
placeholder='Password'
secureTextEntry={true}
/>
<TouchableOpacity style={styles.button} onPress={this.handleSignUp}>
<Text style={styles.buttonText}>Signup</Text>
</TouchableOpacity>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center'
},
inputBox: {
width: '85%',
margin: 10,
padding: 15,
fontSize: 16,
borderColor: '#d3d3d3',
borderBottomWidth: 1,
textAlign: 'center'
},
button: {
marginTop: 30,
marginBottom: 20,
paddingVertical: 5,
alignItems: 'center',
backgroundColor: '#FFA611',
borderColor: '#FFA611',
borderWidth: 1,
borderRadius: 5,
width: 200
},
buttonText: {
fontSize: 20,
fontWeight: 'bold',
color: '#fff'
},
buttonSignup: {
fontSize: 12
}
})
export default Signup
Login.js
import React from 'react'
import { View, TextInput, StyleSheet, TouchableOpacity, Text, Button } from 'react-native'
import { createAppContainer, createSwitchNavigator } from 'react-navigation'
class Login extends React.Component {
state = {
email: '',
password: ''
}
render() {
return (
<View style={styles.container}>
<TextInput
style={styles.inputBox}
value={this.state.email}
onChangeText={email => this.setState({ email })}
placeholder='Email'
autoCapitalize='none'
/>
<TextInput
style={styles.inputBox}
value={this.state.password}
onChangeText={password => this.setState({ password })}
placeholder='Password'
secureTextEntry={true}
/>
<TouchableOpacity style={styles.button}>
<Text style={styles.buttonText}>Login</Text>
</TouchableOpacity>
<Button
title="Don't have an account yet? Sign up"
onPress={() => this.props.navigation.navigate('Signup')}
/>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center'
},
inputBox: {
width: '85%',
margin: 10,
padding: 15,
fontSize: 16,
borderColor: '#d3d3d3',
borderBottomWidth: 1,
textAlign: 'center'
},
button: {
marginTop: 30,
marginBottom: 20,
paddingVertical: 5,
alignItems: 'center',
backgroundColor: '#F6820D',
borderColor: '#F6820D',
borderWidth: 1,
borderRadius: 5,
width: 200
},
buttonText: {
fontSize: 20,
fontWeight: 'bold',
color: '#fff'
},
buttonSignup: {
fontSize: 12
}
})
export default Login
Profile.js
import React from 'react'
import { View, Text, StyleSheet } from 'react-native'
class Profile extends React.Component {
render() {
return (
<View style={styles.container}>
<Text>Profile Screen</Text>
</View>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center'
}
})
export default Profile
From the docs: https://reactnavigation.org/docs/en/hello-react-navigation.html
The current SignUp code is only a React.Component.
Make sure you're creating both an AppNavigator and createAppContainer() per react-navigation documentation.
import React from 'react';
import { View, Text } from 'react-native';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
class HomeScreen extends React.Component {
render() {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Text>Home Screen</Text>
</View>
);
}
}
const AppNavigator = createStackNavigator({
Home: {
screen: HomeScreen,
},
});
export default createAppContainer(AppNavigator);

About this.state function in React Native App

Hello this is my code. When I try to fill the text box then the error come i.e. ('this.setState is not a function.(In this.setState({emal:email)} this.setState is underfined').
Here is my code:
import React from 'react';
import {
Image,
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
TextInput,
TouchableHighlight,
Alert,
} from 'react-native';
export default function LoginScreen() {
onClickListener = (viewId) => {
Alert.alert("Alert", "You can't "+viewId);
}
return (
https://png.icons8.com/message/ultraviolet/50/3498db'}}/>
this.setState({email})}/>
<View style={styles.inputContainer}>
<Image style={styles.inputIcon} source={{uri: 'https://png.icons8.com/key-2/ultraviolet/50/3498db'}}/>
<TextInput style={styles.inputs}
placeholder="Password"
secureTextEntry={true}
underlineColorAndroid='transparent'
onChangeText={(password) => this.setState({password})}/>
</View>
<TouchableHighlight style={[styles.buttonContainer, styles.loginButton]} onPress={() => this.onClickListener('login')}>
<Text style={styles.loginText}>Login</Text>
</TouchableHighlight>
<TouchableHighlight style={styles.buttonContainer} onPress={() => this.onClickListener('restore_password')}>
<Text>Forgot your password?</Text>
</TouchableHighlight>
<TouchableHighlight style={styles.buttonContainer} onPress={() => this.onClickListener('register')}>
<Text>Register</Text>
</TouchableHighlight>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#DCDCDC',
},
inputContainer: {
borderBottomColor: '#F5FCFF',
backgroundColor: '#FFFFFF',
borderRadius:30,
borderBottomWidth: 1,
width:250,
height:45,
marginBottom:20,
flexDirection: 'row',
alignItems:'center'
},
inputs:{
height:45,
marginLeft:16,
borderBottomColor: '#FFFFFF',
flex:1,
},
inputIcon:{
width:30,
height:30,
marginLeft:15,
justifyContent: 'center'
},
buttonContainer: {
height:45,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginBottom:20,
width:250,
borderRadius:30,
},
loginButton: {
backgroundColor: "#00b5ec",
},
loginText: {
color: 'white',
}
});
That is the problem
export default function LoginScreen()
Change it to the
export default class LoginScreen extends Component
For using state, it must a stateful component rather than stateless component, So you have to change your functional component into Class.
change
export default function LoginScreen()
to
export default class LoginScreen extends React.Component
In react-native setState function has syntax
this.setState({someField:someValue})
you are using wrong syntax there, you have to give state name and value
this.setState({email})
this.setState({password})
these line should be like -
this.setState({ email: value })
this.setState({password: value })
if you want to use functional components you can use the UseState hook like this
by importing and initializing the state as shown below:
import React,{useState} from 'react';
export default function LoginScreen() {
const [email,setEmail]=useState(initialValues);
//setEmail function can be used for changing the state
}
use can see the usage of the useState here [https://reactjs.org/docs/hooks-state.html]
hope this helps for you
if you want to use functional components use react hooks,
otherwise use class component as below.
import React, { Component } from 'react';
import { Image, StyleSheet, Text, View, TextInput, TouchableHighlight, Alert } from 'react-native';
export default class LoginScreen extends Component {
onClickListener = viewId => {
Alert.alert('Alert', "You can't " + viewId);
};
render() {
return (
<View>
<View style={styles.inputContainer}>
<Image
style={styles.inputIcon}
source={{uri: 'https://png.icons8.com/key-2/ultraviolet/50/3498db'}}
/>
<TextInput
style={styles.inputs}
placeholder="Password"
secureTextEntry={true}
underlineColorAndroid="transparent"
onChangeText={password => this.setState({password})}
/>
</View>
<TouchableHighlight
style={[styles.buttonContainer, styles.loginButton]}
onPress={() => this.onClickListener('login')}>
<Text style={styles.loginText}>Login</Text>
</TouchableHighlight>
<TouchableHighlight
style={styles.buttonContainer}
onPress={() => this.onClickListener('restore_password')}>
<Text>Forgot your password?</Text>
</TouchableHighlight>
<TouchableHighlight
style={styles.buttonContainer}
onPress={() => this.onClickListener('register')}>
<Text>Register</Text>
</TouchableHighlight>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#DCDCDC',
},
inputContainer: {
borderBottomColor: '#F5FCFF',
backgroundColor: '#FFFFFF',
borderRadius: 30,
borderBottomWidth: 1,
width: 250,
height: 45,
marginBottom: 20,
flexDirection: 'row',
alignItems: 'center',
},
inputs: {
height: 45,
marginLeft: 16,
borderBottomColor: '#FFFFFF',
flex: 1,
},
inputIcon: {
width: 30,
height: 30,
marginLeft: 15,
justifyContent: 'center',
},
buttonContainer: {
height: 45,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginBottom: 20,
width: 250,
borderRadius: 30,
},
loginButton: {
backgroundColor: '#00b5ec',
},
loginText: {
color: 'white',
},
});

How to get total view to center in react native

I am new to react native, and I have created one sample login form. In this form i want to align total view to center. I tried this way but not working, Can You guide me how to achieve this.
My login class is
import React, {Component} from 'react';
import {AppRegistry,Text, View,TextInput,TouchableOpacity,StyleSheet} from 'react-native';
export default class Login extends Component{
render(){
return(
<View style={styles.container}>
<TextInput style={styles.textInput} placeholder="Acc No/User ID"/>
<TextInput style={styles.textInput} placeholder="Password"/>
<TouchableOpacity style={styles.btn} onPress={this.login}><Text>Log In</Text></TouchableOpacity>
</View>
);
}
login=()=>{
alert("testing......");
// this.props.navigation.navigate('Second');
}
}
AppRegistry.registerComponent('Login', () => Login);
const styles = StyleSheet.create({
container:{
justifyContent: 'center',
alignItems: 'center',
},
header: {
fontSize: 24,
marginBottom: 60,
color: '#fff',
fontWeight: 'bold',
},
textInput: {
alignSelf: 'stretch',
padding: 10,
marginLeft: 80,
marginRight:80,
},
btn:{
alignSelf: 'stretch',
backgroundColor: '#01c853',
padding: 10,
marginLeft: 80,
marginRight:80,
alignItems: 'center',
}
});
And the following is the screen shot of above code.
And i tried with the bellow code, but not working
container:{
justifyContent: 'center',
alignItems: 'center',
flex:1
},
So please help me, how to do this?
Thanks In Advance..
Use the flex display : https://css-tricks.com/snippets/css/a-guide-to-flexbox/
import React, { Component } from 'react';
import { AppRegistry, Text, View, TextInput, TouchableOpacity, StyleSheet } from 'react-native';
export default class Login extends Component {
render() {
return (
<View style={styles.container}>
<TextInput style={styles.textInput} placeholder="Acc No/User ID" />
<TextInput style={styles.textInput} placeholder="Password" />
<TouchableOpacity style={styles.btn} onPress={this.login}><Text>Log In</Text></TouchableOpacity>
</View>
);
}
login = () => {
alert("testing......");
// this.props.navigation.navigate('Second');
}
}
AppRegistry.registerComponent('Login', () => Login);
const styles = StyleSheet.create({
container: {
display: 'flex',
flexDirection: 'column',
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
header: {
fontSize: 24,
color: '#fff',
fontWeight: 'bold',
},
textInput: {
padding: 10,
textAlign: 'center',
},
btn: {
backgroundColor: '#01c853',
paddingVertical: 10,
paddingHorizontal: 50,
}
});
And by the way, you could have easily found an answer with a simple search (Vertically center view react-native) : https://moduscreate.com/blog/aligning-children-using-flexbox-in-react-native/
just add flex :1 to your container style
container:{
flex:1,
justifyContent: 'center',
alignItems: 'center',
}
import React,{Component} from 'react';
import {View,Text,TextInput, Button,StyleSheet,Alert} from 'react-native';
class App extends Component{
state = {
userId:'',
password:'',
};
render(){
return(
<View style={styles.container}>
<View>
</View>
<View>
<TextInput
placeholder="User ID"
style={styles.loginTextInput}
onChangeText={(value) => this.setState({userId: value})}
value={this.state.userId}
></TextInput>
<TextInput
placeholder="Password"
style={styles.loginTextInput}
onChangeText={(value)=>this.setState({password:value})}
></TextInput>
<Button
title="Login"
style={styles.loginBtn}
onPress={this.loginCheck}
></Button>
</View>
</View>
)
}
loginCheck=()=>{
if((this.state.userId=='admin') && (this.state.password=='admin')){
Alert.alert("Login Success");
}else{
Alert.alert("User and password is not match\n Please try again");
}
}
}
export default App;
const styles = StyleSheet.create({
container:{
flex:1,
justifyContent:'center',
},
loginTextInput:{
borderColor:'#ebe9e6',
borderWidth:1,
margin:5,
},
loginBtn:{
backgroundColor: '#01c853',
paddingVertical: 10,
paddingHorizontal: 50,
}
})

React Native can't click TouchableOpacity or TextInput

In my React Native project I have a TextInput and a TouchableOpacity component at the top of the screen that for some reason cannot be clicked. It worked at some point while I was working on the project, but for some reason it no longer recognizes clicks or key events. The component is as follows:
import React, { Component } from "react";
import {
AsyncStorage,
Dimensions,
FlatList,
Platform,
StyleSheet,
Text,
TextInput,
TouchableOpacity,
View
} from "react-native";
import styles from "./style/styles";
import NotificationBar from "./components/NotificationBar";
export default class App extends Component {
constructor(props) {
super(props);
this.data = [];
this._initData();
}
_initData() {
for (let i = 0; i < 500; i++) {
this.data.push({
// key: i,
id: "ABC" + i,
name: "Random Name",
value: 50 * i
});
}
}
_renderItem = ({ item }) => {
return (
<View style={styles.itemContainer}>
<Text style={styles.textItem}>{item.id}</Text>
</View>
);
};
render() {
return (
<View>
<NotificationBar />
<View style={{ flex: 1, flexDirection: "column" }}>
<View style={{ flex: 1, flexDirection: "row" }}>
<View
style={{
width: (Dimensions.get("window").width / 3) * 2,
height: 50,
backgroundColor: "white"
}}
>
<TextInput
placeholder="New List Name"
style={styles.textInputStyle}
/>
</View>
<View
style={{
width: Dimensions.get("window").width / 3,
height: 50,
backgroundColor: "#4ce31e"
}}
>
<TouchableOpacity
style={styles.button}
onPress={this.testSetStorage}
>
<Text> Create List </Text>
</TouchableOpacity>
</View>
</View>
</View>
<View style={{ paddingTop: 50 }}>
<FlatList
data={this.data}
renderItem={this._renderItem}
style={{ alignSelf: "stretch" }}
keyExtractor={(item, index) => item.id}
/>
</View>
</View>
);
}
}
The style sheet is:
import { StyleSheet } from 'react-native';
export default StyleSheet.create({
statusBarBackground: {
height: 20,
backgroundColor: 'white',
},
textInputStyle: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
textAlign: 'center',
borderWidth: 1,
borderRadius: 6,
},
button: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
width: 100,
paddingLeft: 20,
},
container: {
flex: 1,
justifyContent: 'center',
paddingHorizontal: 10
},
});
My best guess is that it the issue would have something to do with the parent View components that the TouchableOpacity and TextInput components are in, but I'm not sure. How can I get those components to recognize clicks and respond to them? I'm running on an iPhone 7 emulator.
You have not defined testSetStorage function in your component.
You need to testSetStorage = () => {console.log("Tapped")} outside render function.