I am learning react-native and I wanted to do something simple where the user can enter some information like name or something and then when he/she clicks the button, it will display on the screen hello so and so. I have my onChangeText setting the state to what the user passes but it doesn't update. Also clicking the button doesn't show anything. I will paste my code down below. Any help or suggestions.
app.js
import { Button } from "react-native";
import React, { Component } from "react";
import {
Platform,
StyleSheet,
Text,
View,
Alert,
TextInput
} from "react-native";
const instructions = Platform.select({
ios: "Press Cmd+R to reload,\n" + "Cmd+D or shake for dev menu",
android:
"Double tap R on your keyboard to reload,\n" +
"Shake or press menu button for dev menu"
});
type Props = {};
export default class App extends Component<Props> {
constructor() {
super();
this.state = {
text: "Hello "
};
this.handleChange = this.handleChange.bind(this);
}
handleChange = typedText => {
this.setState({
text: typedText
});
console.log(text);
};
render() {
return (
<View style={styles.container}>
<Text>{this.state.value}</Text>
<Button onPress={this.handleChange} title="Click Me " />
<TextInput
placeholder="Type your name here"
onChangeText={typedText => {
this.setState({
text: typedText
});
}}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "#F5FCFF"
},
welcome: {
fontSize: 20,
textAlign: "center",
margin: 10
},
instructions: {
textAlign: "center",
color: "#333333",
marginBottom: 5
}
});
You are setting the state in handlechange (the onpress function) as well which is not required at all. There wont be an argument of text in your onPress you are resetting the text value in the state. And the text inside the handleChange will be undefined as you dont set it anywhere.
the code should be something like below.
export default class App extends Component {
constructor() {
super();
this.state = {
text: "Hello "
};
this.handleChange = this.handleChange.bind(this);
}
onPress = () => {
console.log("current ==> ", this.state);
alert(this.state.text);
};
handleChange = typedText => {
console.log("update => ", typedText);
this.setState(
{
text: typedText
}
);
};
render() {
return (
<View style={styles.container}>
<Text>{this.state.value}</Text>
<Button onPress={this.onPress} title="Click Me " />
<TextInput
placeholder="Type your name here"
onChangeText={this.handleChange}
/>
</View>
);
}
}
The issue was, on Press of button we are calling a function which expects a 'text' but in actual it is an event.
Check this codesandbox
Related
this code does not Display the list(places) which places i added to it using add_Button.
Generally working of this code is this that i input text into this react-native app using TextInput Component, after this i press the Add Button to add this text into a list(places), after this it automatically display all the entered text.
e.g if i enter the place by 1st time it only display that text, but if i enter another text it displays that text as well as the first one.
import React, {Component} from 'react';
import {View, TextInput, StyleSheet, Button, Text} from 'react-native';
export default class App extends Component
{
state = {
placeName: "",
places: []
};
placeNameChangeHandler=(val)=>
{
this.setState({
InputValue: val
})
};
placeSubmitHandler = () =>{
if(this.state.placeName.trim() === "")
{
return;
}
this.setState(prevState => {
return {
places : prevState.places.concat(prevState.placeName)
};
});
};
render()
{
const placesOutput = this.state.places.map((place, i) =>(
<Text key={i} backgroundColor = 'black' >{place}</Text>
));
return(
<View style={Styles.container}>
<View style = {Styles.inputContainer}>
<TextInput
placeholder = "Search place?"
value = {this.setState.placeName}
onChangeText = {this.placeNameChangeHandler}
style={Styles.placeInput}
/>
<Button
title='Add'
style = {Styles.placeButton}
onPress = {this.placeSubmitHandler}
/>
</View>
<View>{placesOutput}</View>
</View>
);
}
}
const Styles = StyleSheet.create({
container: {
flex:1,
padding: 10,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'flex-start'
},
inputContainer: {
width: "100%",
flexDirection : 'row',
justifyContent: 'space-between',
alignItems:'center'
},
placeInput: {
width: "70%"
},
placeButton: {
width: "30%"
}
})
This is not 100% correct, but I'll write it down.
This seems to happen because of setState.
First.
Change to value = {this.setState.placeName} to value = {this.state.placeName}
<TextInput
placeholder = "Search place?"
value = {this.state.placeName}
onChangeText = {this.placeNameChangeHandler}
style={Styles.placeInput}
/>
Next.
Change setState in placeNameChangeHandler
placeNameChangeHandler=(val)=>{
this.setState({
placeName: val
})
};
And
Add Initializing placeName
placeSubmitHandler=()=>{
if(this.state.placeName.trim() === "")
{
return;
}
this.setState(prevState => {
return {
places : prevState.places.concat(prevState.placeName),
placeName : ""
};
});
};
Sorry for my stupid English.
I hope you understand :)
So I've a TextInput and the placeholder has a styling.
For this, I place a Text with position: 'absolute' and zIndex: 1 before the TextInput
activeField(){
this.setState({active: true})
}
render(){
return(
{ !this.state.active &&
<Text style={STYLES.textInputPlaceholder}>
{this.props.placeholder}
</Text>
}
<TextInput
style={STYLES.textInputField}
onFocus={() => this.activeField()}
/>
)
}
Now, the Text component which has the placeholder, when I press on it, I should be able press at the placeholder, which is the Text component here and be able to call the onFocus method of TextInput
I hope I'm able to clearly explain my problem.
We would not be able to trigger the onFocus event-listener of the TextInput by clicking on the Text. However, we can make it appear like that is happening with some clever CSS.
Make sure that the background of the TextInput is transparent or
at least matching that of the Text. That way Text is still visible when we give position: absolute.
Then we
We need the zIndex of the Text to be lower than the zIndex of the
TextInput. That way TextInput is actually in front of Text. So while it looks like you're clicking on the placeholder, you are actually just clicking on the TextInput and that will trigger the onFocus event.
Try this:
import React, { Component } from "react";
import { StyleSheet, Text, TextInput } from "react-native";
class App extends Component {
state = {
active: false,
text: ""
};
activeField = () => {
console.log("focused");
this.setState({
active: true
});
};
handleOnBlur = () => {
if (this.state.text.length === 0) {
this.setState({
active: false
});
}
};
render() {
return (
<div>
{!this.state.active && (
<Text style={STYLES.textInputPlaceholder}>
{this.props.placeholder}
</Text>
)}
<TextInput
style={STYLES.textInputField}
onChangeText={text => this.setState({ text })}
onFocus={this.activeField}
value={this.state.text}
onBlur={this.handleOnBlur}
/>
</div>
);
}
}
const STYLES = StyleSheet.create({
app: {
marginHorizontal: "auto"
},
textInputField: {
zIndex: 1,
width: 300,
borderColor: "black",
borderWidth: 1
},
textInputPlaceholder: {
zIndex: -1,
color: "blue",
position: "absolute",
backgroundColor: "transparent"
}
});
export default App;
App.defaultProps = {
placeholder: "Hello"
};
Here's the working sandbox: https://codesandbox.io/s/react-native-on23p
I am using the package called react-native-phone-input, and when the phone number is changed it runs the function this.updateInfo() which updates the state. In my code, the icon color is dependent on the state and changes based on whether the phone number is valid. This works, however, when the state is changed, the screen re-renders and the keyboard is dismissed since the text field loses focus. Is there another way I can change the icons color? Or is there a way that I can keep the focus on the text field?
This is what I am referring to:
import React, { Component } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, TextInput, Keyboard} from 'react-native';
import { Icon } from 'react-native-elements';
import KeyboardAccessory from 'react-native-sticky-keyboard-accessory';
import PhoneInput from 'react-native-phone-input';
export default class PhoneLogin extends Component {
constructor() {
super();
this.state = {
valid: "",
type: "",
value: "",
iconColor: "#D3D3D3",
};
this.updateInfo = this.updateInfo.bind(this);
}
updateInfo() {
this.setState({
valid: this.phone.isValidNumber(),
type: this.phone.getNumberType(),
value: this.phone.getValue().replace(/[- )(]/g,''),
});
}
render() {
return (
<View style={styles.container}>
<PhoneInput
ref={ref => {
this.phone = ref;
}}
style={{height: 50, borderColor:'#44c0b9', borderBottomWidth:2}}
onChangePhoneNumber={ (phone) => {this.updateInfo()} }
/>
<KeyboardAccessory backgroundColor="#fff">
<View style={{ alignItems: 'flex-end', padding:10 }}>
<Icon
raised
reverse
color={(this.state.valid) ? "#44c0b9" : "#D3D3D3"}
name='arrow-right'
type='font-awesome'
onPress={ Keyboard.dismiss()}
/>
</View>
</KeyboardAccessory>
</View>
);
}
}
let styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
padding: 20,
paddingTop: 60
},
info: {
// width: 200,
borderRadius: 5,
backgroundColor: "#f0f0f0",
padding: 10,
marginTop: 20
},
button: {
marginTop: 20,
padding: 10
}
});
In your onPress of your Icon you need to send an arrow function.
The Icon should be like this
<Icon
raised
reverse
color={(this.state.valid) ? "#44c0b9" : "#D3D3D3"
name='arrow-right'
type='font-awesome'
onPress={() => Keyboard.dismiss()}
/>
The problem was the Keyboard.dismiss() was immediately running every time the component re-rendered thus dismissing your keyboard.
Hope this helps!
Something does not make sense with my code.
I am using React Native to create a app.
In that app I am using a Tab Navigator.
It works fine until I call this.setState which for some reason triggers a unwanted Tab change from one tab to the other.
Why would setState trigger a Tab change??
This is my code:
import React from 'react';
import { StyleSheet, Text, View, FlatList, TextInput, StatusBar, Button } from 'react-native';
import { TabNavigator } from 'react-navigation';
import { Constants } from 'expo'
import { purple, white } from './utils/colors'
const R = require('ramda')
function CustomStatusBar({ backgroundColor, ...props }){
return (
<View style={{backgroundColor, height: Constants.statusBarHeight}}>
<StatusBar translucent backgroundColor={backgroundColor} {...props} />
</View>
)
}
export default class App extends React.Component {
constructor(props){
super(props)
this.handleDeckTitle = this.handleDeckTitle.bind(this)
}
state = {
title: ''
}
renderItem = (sample) => {
console.log('renderItem', sample)
return <Text>SAMPLE DATA</Text>
}
handleDeckTitle(e){
console.log('handleDeckTitle')
console.log('e', e)
console.log('this.state', this.state)
this.setState((prevState, props) => ({
title: e
}));
}
submitDeckTitle(){
console.log('submitDeckTitle')
}
render() {
console.log('R', R)
const Decks = () => {
return (
<View>
<CustomStatusBar backgroundColor={purple} barStyle='light-content' />
<Text>Decks!</Text>
</View>
)
}
const NewDeck = () => {
return (
<View>
<CustomStatusBar backgroundColor={purple} barStyle='light-content' />
<Text>What is the title of your new deck?</Text>
<TextInput style = {styles.input} onChangeText={this.handleDeckTitle}/>
<Button onPress={this.submitDeckTitle} title="Submit" />
</View>
)
}
const Tabs = TabNavigator({
Decks: {
screen: Decks
},
'New Deck': {
screen: NewDeck
},
});
return (
<Tabs />
);
}
}
const styles = StyleSheet.create({
container: {
paddingTop: 23,
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
input: {
margin: 15,
height: 40,
borderColor: '#7a42f4',
borderWidth: 1
},
});
I don't see what is wrong with this code.
In fact I think it should just work normally but it does not.
It triggers a tab change when I call handleDeckTitle which then calls this.setState
Got it to work now.
I changed the part that calls setState to be be a Separate Component with its own state.
Here is the code:
import React from 'react';
import { StyleSheet, Text, View, FlatList, TextInput, StatusBar, Button } from 'react-native';
import { TabNavigator } from 'react-navigation';
import { Constants } from 'expo'
import { purple, white } from './utils/colors'
const R = require('ramda')
function CustomStatusBar({ backgroundColor, ...props }){
return (
<View style={{backgroundColor, height: Constants.statusBarHeight}}>
<StatusBar translucent backgroundColor={backgroundColor} {...props} />
</View>
)
}
const Decks = () => {
return (
<View>
<CustomStatusBar backgroundColor={purple} barStyle='light-content' />
<Text>Decks!</Text>
</View>
)
}
class NewDeck extends React.Component {
constructor(props){
super(props)
this.handleDeckTitle = this.handleDeckTitle.bind(this)
}
state = {
title: ''
}
handleDeckTitle(e){
console.log('handleDeckTitle')
console.log('e', e)
console.log('this.state', this.state)
this.setState((prevState, props) => ({
title: e
}));
}
render(){
return (
<View>
<CustomStatusBar backgroundColor={purple} barStyle='light-content' />
<Text>What is the title of your new deck?</Text>
<TextInput style = {styles.input} onChangeText={this.handleDeckTitle}/>
<Button onPress={this.submitDeckTitle} title="Submit" />
</View>
)
}
}
const Tabs = TabNavigator({
Decks: {
screen: Decks
},
'New Deck': {
screen: NewDeck
},
});
export default class App extends React.Component {
constructor(props){
super(props)
// this.handleDeckTitle = this.handleDeckTitle.bind(this)
}
state = {
title: ''
}
renderItem = (sample) => {
console.log('renderItem', sample)
return <Text>SAMPLE DATA</Text>
}
submitDeckTitle(){
console.log('submitDeckTitle')
}
render() {
console.log('R', R)
return (
<Tabs />
);
}
}
const styles = StyleSheet.create({
container: {
paddingTop: 23,
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
input: {
margin: 15,
height: 40,
borderColor: '#7a42f4',
borderWidth: 1
},
});
Here's my code. I have tried many different things based on react-navigation and navigators but still getting Undefined is not an object(evaluating _this3.props.navigation.navigate).
I even tried restarting the package manager and running project again.
I am running my project on Android Device.
Please help with relevant lines to my code.
import React, {
Component
} from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View,
Image,
Button,
Alert,
} from 'react-native';
import {
StackNavigator,
} from 'react-navigation';
import ProfileScreen from './ProfileScreen'
//import HomeScreen from './HomeScreen'
export const AwesomeProject = StackNavigator({
//Home: {screen: HomeScreen},
Profile: {
screen: ProfileScreen,
navigationOptions : {
title: 'Welcome',
}
},
});
const onButtonPress = () => {
Alert.alert('Button has been pressed!');
};
class Blink extends Component {
constructor(props) {
super(props);
this.state = {
showText: true
};
// Toggle the state every second
setInterval(() => {
this.setState({
showText: !this.state.showText
});
}, 1000);
}
render() {
let display = this.state.showText ? this.props.text : ' ';
return (
<Text> {display} </Text>
);
}
}
export default class HomeScreen extends Component {
constructor(props){
super(props)
}
render() {
//const {navigate} = this.props.navigation;
return (
<View style={styles.container}>
<Text style={styles.welcome}>
<Blink text='Hello!'/>
</Text>
<Button
//onPress = {onButtonPress}
onPress = {() => this.props.navigation.navigate('Profile').bind(this)}
title="Lets Go!"
color="#851884"
accessibilityLabel="Learn more about people">
</Button>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#456987',
},
welcome: {
fontSize: 20,
textAlign: 'center',
color: '#DD5522',
margin: 10,
},
});