Getting null instead of text - react-native

I'm trying to get the text from two text fields I have.
But when I try to log the text to the console it always prints nothing, It has the LOG tag of course, but nothing else.
This is my code:
class Login extends React.Component {
state = {
email : '',
password: '',
}
handleLogin = () => {
console.log(this.state.email);
};
render() {
return(
<View style={styles.superContainer}>
<View style={styles.formContainer}>
<AppTextInput
placeHolderText="Email#Address.com"
onChangeText={(text) => this.setState({email: text})}/>
<AppTextInput
placeHolderText="Password"
onChangeText={(text) => this.setState({password: text})}/>
</View>
<View style={styles.buttonContainer}>
<AppButton
title="LOGIN"
onPress={this.handleLogin}
/>
</View>
</View>
);
}
}
I searched for an answer, but it seems like it should work. It is written just like in other answers I saw to the same question, and it is written like that on the docs I saw.
What am I doing wrong?
As request, I added an image of the console:
EDIT: I now tried to change the 'email' in the this.state part, when logging it is showing, it seems like the TextInput won't get the text on onChangeText

Try this:
import {TextInput} from 'react-native';
class Login extends React.Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: ''
};
}
handleLogin = () => {
console.log(this.state.email);
};
render() {
return(
<View style={styles.superContainer}>
<View style={styles.formContainer}>
<TextInput
placeHolderText="Email#Address.com"
onChangeText={(email) => this.setState({email})}/>
<TextInput
placeHolderText="Password"
onChangeText={(password) => this.setState({password})}/>
</View>
<View style={styles.buttonContainer}>
<AppButton
title="LOGIN"
onPress={this.handleLogin}
/>
</View>
</View>
);
}
}

I can verify that the following code is working on Snack, I have slightly modified some elements (nothing major) and used the alert, instead of console.log. You may directly paste it onto snack to view the result.
import {TextInput} from 'react-native';
import React from 'react'
import { Text, View, Button } from 'react-native';
class Login extends React.Component {
state = {
email : '',
password: '',
}
handleLogin = () => {
alert(this.state.password + " " + this.state.email);
};
render() {
return(
<View>
<View>
<TextInput
placeHolderText="Email#Address.com"
onChangeText={(text) => this.setState({email: text})}/>
<TextInput
placeHolderText="Password"
onChangeText={(text) => this.setState({ password: text })}
/>
</View>
<View >
<Button
title="LOGIN"
onPress={this.handleLogin}
/>
</View>
</View>
);
}
}
export default Login;

Finally figured it out, the problem was that I was using a custom TextInput (aka AppTextInput) and didn't pass it the onChangeText.
Adding to AppTextInput onChangeText={this.props.onChangeText} fixed the issue.
This is the full render function of AppTextInput:
render() {
const { isFocused } = this.state;
const {onFocus, onBlur, onChangeText} = this.props;
return (
<TextInput
placeholder= {this.props.placeHolderText}
selectionColor = {COLORS.appOrange}
underlineColorAndroid={
isFocused ? COLORS.appOrange : COLORS.appGray
}
onChangeText={this.props.onChangeText}
onFocus = {this.handleFocus}
onBlur = {this.handleBlur}
style = {styles.textInput}
/>
);
}

Related

Appium React Native Not Ready for Text Input

I've recently switched over to Appium + webdriverIO for E2E testing. Everything is working pretty well except for one test case relating to text input.
Basically, the component under test is a login screen that uses redux-form for form management. I'm constantly getting the error "'"login-field" Other' is not ready for a text input. Neither the accessibility element itself nor its accessible descendants have the input focus". The components are as follow:
SignInScreen.tsx
export class SignInScreen extends React.Component<any> {
render() {
const { handleSubmit, submitting, style } = this.props;
return (
<View style={style}>
<View>
<View>
<Field
name="login"
component={Input}
accessibilityLabel="login-field"
testID="login-field"
/>
<Field
secureTextEntry
name="password"
component={Input}
accessibilityLabel="password-field"
testID="password-field"
/>
</View>
</View>
</View>
);
}
}
Input.tsx
export class Input extends React.Component {
render() {
const {
input,
meta: { error, active, focused },
accessibilityLabel,
testID
} = this.props;
const showError = !active && !!error && !focused;
const errorText = "ERROR!"
return (
<View style={[style, styles.container]}>
<TextInput
autoCapitalize="none"
value={input.value}
onChangeText={input.onChange}
onFocus={input.onFocus}
onBlur={input.onBlur}
accessibilityLabel={accessibilityLabel},
testID={testID}
/>
<View style={{height: 30}}>
{showError && (
<Text>{errorText}</Text>
)}
</View>
</View>
);
}
}
SignInScreen.test.ts
describe('Sign In Screen Test', () => {
let client;
beforeAll(async () => {
// set up code
});
afterAll(async () => {
// tear down code
});
it('Can login', async () => {
const loginField = await client.$('~login-field');
await loginField.setValue('test#gmail.com'); // error here
const passwordField = await client.$('~password-field');
await passwordField.set('password' + '\n');
});
});
I do realize that the test cases work when I either add an additional <TextInput /> on top of the existing <TextInput /> component in the Input.tsx component as follows:
Input.tsx
export class Input extends React.Component {
render() {
const {
input,
meta: { error, active, focused },
accessibilityLabel,
testID
} = this.props;
const showError = !active && !!error && !focused;
const errorText = "ERROR!"
return (
<View style={[style, styles.container]}>
<TextInput />
<TextInput
autoCapitalize="none"
value={input.value}
onChangeText={input.onChange}
onFocus={input.onFocus}
onBlur={input.onBlur}
accessibilityLabel={accessibilityLabel},
testID={testID}
/>
<View style={{height: 30}}>
{showError && (
<Text>{errorText}</Text>
)}
</View>
</View>
);
}
}
or I remove the fixed height in the View component that nests the error message as follows:
Input.tsx
export class Input extends React.Component {
render() {
const {
input,
meta: { error, active, focused },
accessibilityLabel,
testID
} = this.props;
const showError = !active && !!error && !focused;
const errorText = "ERROR!"
return (
<View style={[style, styles.container]}>
<TextInput
autoCapitalize="none"
value={input.value}
onChangeText={input.onChange}
onFocus={input.onFocus}
onBlur={input.onBlur}
accessibilityLabel={accessibilityLabel},
testID={testID}
/>
<View>
{showError && (
<Text>{errorText}</Text>
)}
</View>
</View>
);
}
}
So what gives? I'm really lost as to what's causing Appium to not pick up the input focus without making the above adjustments.
I believe this is a recent bug with Appium - https://github.com/appium/java-client/issues/1386
You should NOT specify accessibilityLabel for ios separate props for ios and android like so try next workaround:
export default function testID(id) {
return Platform.OS === 'android'
? {
accessible : true,
accessibilityLabel: id,
}
: {
testID: id,
};
}
and then
<TextInput
{...otherProps}
{...testID('some-testID')}
/>

Passing multiple data through to next scene

I'm lost as to how to send through multiple input of data through to the next scene in my app. I have no problem with sending through one input of data "text1".
This is my sample code below.
import { Actions } from 'react-native-router-flux';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
text1: '',
text2: '',
};
}
render() {
return (
<View>
<TextInput
style={styles.input}
underlineColorAndroid="transparent"
onChangeText={text1 => this.setState({ text1 })}
/>
</View>
<View style={styles.inputContainer}>
<TextInput
style={styles.input}
underlineColorAndroid="transparent"
onChangeText={text2 => this.setState({ text2 })}
/>
</View>
<TouchableOpacity
style={styles.btnNext}
onPress={this.onPressNext.bind(this)}>
<Text style={styles.btnText}>Next</Text>
</TouchableOpacity>
);
}
Below is where i think needs fixing because the + sign isn't allowing to pass two states?
onPressNext() {
Actions.scene2({text1: this.state.text1} +
{text2: this.state.text2});
}
}
Instead of trying to pass 2 different objects, just pass it like:
Actions.scene2({text1: this.state.text1,
text2: this.state.text2})

React Native - Is not a function - Is Undefined

I have the following code in React Native
import React from "react";
import {
StyleSheet,
Text,
View,
Button,
TextInput,
Image,
ScrollView
} from "react-native";
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
apiData: [],
};
this.getButton();
}
deleteButton(Id){
fetch("http://192.168.2.22:9090/usuario/" + (Id), {
method: "DELETE"
})
.then(responseData => {
console.log(responseData.rows);
})
.done();
this.dataId = null;
}
render() {
const data = this.state.apiData;
let dataDisplay = data.map(function(jsonData) {
return (
<View style={styles.lista} key={jsonData.id}>
<View style={styles.bordeLista}>
<View style={styles.fila}>
<View style={styles.contenedorfoto}>
<Image
style={styles.foto}
source={require("./img/login.png")}
/>
</View>
<View style={styles.datos}>
<Text>Nombre: {jsonData.nombre}</Text>
<Text>E-mail: {jsonData.email}</Text>
<Text>Telefono: {jsonData.telefono}</Text>
</View>
</View>
<View style={styles.fila}>
<View style={styles.contenedorboton}>
<View style={styles.botoniz}>
<Button title="Modificar" onPress={() => {}} />
</View>
<View style={styles.botonde}>
<Button
title="Eliminar"
onPress={() => this.deleteButton(jsonData.Id)}
color="#ee4c4c"
/>
</View>
</View>
</View>
</View>
</View>
);
});
return (
<Text style={styles.titulo}>Usuarios desde BD MySQL</Text>
<ScrollView>
<View>{dataDisplay}</View>
</ScrollView>
</View>
);
}
}
And I want to call deleteButton() from this button
<Button
title="Eliminar"
onPress={() => this.deleteButton(jsonData.Id)}
color="#ee4c4c"
/>
But I get the following error, That the method is not a function and that it is not defined.
Error
How could I use the function? And I'm setting the parameter well (id). Thank you.
PS: I have deleted parts of the code and only left the most important, if you need the full code I can provide it
You're losing the reference to this because you're using an old-style lambda.
Replace this
data.map(function(jsonData) {
with an arrow function, like this
data.map(jsonData => {

Change the color of Button when onFocus input

Good Morning , I tried a simple component with react-native that changes the color of my button while onFocus().I can't find how to change the color . Here is my component . Have you any ideas ?
import React, {Component} from 'react';
import {
StyleSheet,Text, View, Button,
} from 'react-native';
export default class App extends Component {
render() {
return (
<View style={styles.inputContainer}>
<TextInput
maxHeight={200}
style={styles.textInput}
ref={(r) => {
this.textInputRef = r;
}}
placeholder={'Message'}
underlineColorAndroid="transparent"
onFocus={()=>{/*Here i awant to change the color of Button }}
testID={'input'}
/>
<Button color="transparent" id="ScanButton"
onPress={() => this.setState({text: 'Placeholder Text'})}
title="Scan Barcode"
/>
</View>
)}
First Initialize your variable
constructor(props) {
super(props);
this.state = {
isFocus: false
}
}
In your TextInput add two props onFocus() and onBlur()
<TextInput
maxHeight={200}
style={styles.textInput}
ref={(r) => {
this.textInputRef = r;
}}
placeholder={'Message'}
underlineColorAndroid="transparent"
onBlur={() => this.onBlur()}
onFocus={() => this.onFocus()}
testID={'input'}
/>
add two methods in your class to change the state
onFocus() {
this.setState({
isFocus: true
})
}
onBlur() {
this.setState({
isFocus: false
})
}
and your button style will be like that
<Button
color={this.state.isFocus ? 'red' : 'green'}
id="ScanButton"
onPress={() => this.setState({text: 'Placeholder Text'})}
title="Scan Barcode"
/>
style={{color: this.props.focused ? '#8B327C' :'#3F8B99'}}
try something like this

error: "undefined is not an object(evaluating 'this,props.navigation.navigate')" In React Native

Getting errors when navigating one page to other page in React Native.
error:
undefined is not an object(evaluating 'this,props.navigation.navigate')
code:
import { StackNavigator,NavigationActions } from "react-navigation";
const Navigation = StackNavigator({
Home : {
screen : Home
},
})
export default class App extends React.Component {
submit = () => {
this.props.navigation.navigate('Home');
}
render() {
return (
<View style={styles.container}>
<Text>Enter Log</Text>
<TextInput style={styles.input}
multiline={true}
underlineColorAndroid="transparent"
placeholder="Enter Log"
placeholderTextColor="#9a73ef"
autoCapitalize="none"
onChangeText={this.handlePassword} />
<TouchableOpacity style={styles.submitButton} onPress={() => submit } >
<Text style={styles.submitButtonText}> Submit </Text>
</TouchableOpacity>
</View>
);
}
}
}
You have to bind your method:
import { StackNavigator,NavigationActions } from "react-navigation";
const Navigation = StackNavigator({
Home : {
screen : Home
},
})
export default class App extends React.Component {
constructor(props) {
super(props);
this.submit = this.submit.bind(this);
}
render() {
return (
<View style={styles.container}>
<Text>Enter Log</Text>
<TextInput style={styles.input}
multiline={true}
underlineColorAndroid="transparent"
placeholder="Enter Log"
placeholderTextColor="#9a73ef"
autoCapitalize="none"
onChangeText={this.handlePassword} />
<TouchableOpacity style={styles.submitButton} onPress={this.submit} >
<Text style={styles.submitButtonText}> Submit </Text>
</TouchableOpacity>
</View>
);
}
submit() {
this.props.navigation.navigate('Home');
}
}
Explanation: Binding context when calling ES6 method. How to access object from within method called as callback?
Try changing your onPress value to this:
onPress={this.submit}
Also, I don't see you importing your Home component to where you assign it as a screen.