so I am trying to perform some onChange event, as I learned, but somehow it throws me the error that the onChange function is undefined. The right dependency is installed (react-hook-form).
Here is my code.
Someone a idea, where the issue is coming from?
https://codesandbox.io/embed/jolly-butterfly-diqb1?fontsize=14&hidenavigation=1&theme=dark
import React from "react";
import {
StyleSheet,
TextInput,
Text,
TouchableOpacity,
Image,
ScrollView
} from "react-native";
import { useForm, Controller } from "react-hook-form";
const AddAddress = () => {
const { control, handleSubmit, errors, reset } = useForm({
defaultValues: {
name: "",
email: ""
}
});
function submit(data) {
console.log(data);
}
return (
<ScrollView contentContainerStyle={styles.container}>
<Text style={styles.title}>React Hook Form</Text>
<Controller
control={control}
name="name"
render={({ onChange, value }) => (
<TextInput
placeholder="Name"
style={styles.input}
onChangeText={(value) => onChange(value)}
/>
)}
/>
<Controller
control={control}
name="email"
render={({ onChange, value }) => (
<TextInput
placeholder="Email"
style={styles.input}
onChangeText={(value) => onChange(value)}
/>
)}
/>
<TouchableOpacity onPress={handleSubmit(submit)}>
<Text style={styles.button}>Submit</Text>
</TouchableOpacity>
</ScrollView>
);
};
export default AddAddress;
It is because you are passing the onChange function dirctly, but it is a part of the field prop, so you should pass them as a named argument
...Controller
render={({
field: { onChange, onBlur, value, name, ref },
fieldState: { invalid, isTouched, isDirty, error },
}) => ( ...
Kindly have a look at the docs : https://react-hook-form.com/api/usecontroller/controller
Or pass in the value field, and use the field.onChange method.
This is the modified code.
The output on submit will be as follows after providing the inputs
{name: "sample", email: "sample#g,co"}
import React from "react";
import {
StyleSheet,
TextInput,
Text,
TouchableOpacity,
Image,
ScrollView
} from "react-native";
import { useForm, Controller } from "react-hook-form";
const AddAddress = () => {
const { control, handleSubmit, errors, reset } = useForm({
defaultValues: {
name: "",
email: ""
}
});
function submit(data) {
console.log(data);
}
return (
<ScrollView contentContainerStyle={styles.container}>
<Text style={styles.title}>React Hook Form</Text>
<Controller
control={control}
name="name"
// ------------ modified here
render={({field}) => (
<TextInput
placeholder="Name"
style={styles.input}
onChange = {(e)=>field.onChange(e)}
value = {field.value}
/>
)}
/>
<Controller
control={control}
name="email"
// ------------ modified here
render={({ field }) => (
<TextInput
placeholder="Email"
style={styles.input}
onChange = {(e)=>field.onChange(e)}
value = {field.value}
/>
)}
/>
<TouchableOpacity onPress={handleSubmit(submit)}>
<Text style={styles.button}>Submit</Text>
</TouchableOpacity>
</ScrollView>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#282828",
alignItems: "center",
justifyContent: "center"
},
title: {
fontSize: 36,
marginBottom: 30,
marginTop: 16,
color: "white"
},
error: {
fontSize: 16,
color: "red",
marginTop: 16,
marginBottom: 16,
marginLeft: 36,
marginRight: 36
},
input: {
fontSize: 18,
borderWidth: 1,
padding: 12,
width: "80%",
borderRadius: 10,
backgroundColor: "white",
marginBottom: 16,
marginTop: 16
},
image: {
width: 120,
height: 120,
borderColor: "orange",
borderWidth: 2,
borderRadius: 100
},
button: {
fontSize: 20,
color: "white",
width: 120,
marginTop: 8,
borderRadius: 10,
backgroundColor: "#c01c00",
padding: 8,
textAlign: "center"
}
});
export default AddAddress;
Related
I have a ScrollView component, and within it I have a form (<AppForm >) that works using Formik and Yup. This form has some input fields (<AppTextInput >). In the form I assign the keyboardType prop for each input field.
The problem is that the fields with keyboardType set to default scroll down the whole ScrollView component when you focus on it, like adding margin to the top of it. This only happens when the keyboardType is set to default.
If I focus on an input field with the keyboardType prop set to numeric, everything works fine.
Any idea of what am I doing wrong?
Here is a gif of what's exactly the problem:
https://giphy.com/gifs/djoHUBAKu9XGyu37OO
And here is my code:
AppFormField (Main screen)
function ActivityFormScreen({ navigation }) {
return (
<View style={styles.container}>
<ActivityIndicator
visible={
postActivityApi.loading ||
editActivityApi.loading ||
getTrabajosApi.loading ||
getCosechasApi.loading ||
getMaquinariasApi.loading
}
/>
<ScrollView style={{ paddingBottom: 500 }}>
<ActivityTitle
text="Información"
name="information-variant"
size={35}
/>
<AppForm
onSubmit={(form) => handleSubmit(form)}
validationSchema={validationShema}
initialValues={{
fecha: getFormValue("fecha"),
finca_id: getFormValue("finca_id"),
lote: getFormValue("lote"),
cosecha: getFormValue("cosecha"),
cultivos: getFormValue("cultivos"),
maquinaria: getFormValue("maquinaria"),
tiempo_actividad: getFormValue("tiempo_actividad"),
productos: getFormValue("productos"),
cantidad: getFormValue("cantidad"),
unidad: getFormValue("unidad"),
hectarea_trabajada: getFormValue("hectarea_trabajada"),
trabajos: getFormValue("trabajos"),
observaciones: getFormValue("observaciones"),
}}
>
<AppFormField
name="fecha"
holder="Fecha"
keyboardType="default"
placeholder="AAAA-MM-DD"
defaultValue={getFormValue("fecha")}
/>
<AppPickerField
name="finca_id"
holder="Granja"
data={context.allFarms} //Seleccionar el array de granjas
pickerPlaceholder="Seleccione una granja"
value={getFormValue("finca_id")}
/>
<AppFormField
name="lote"
holder="Lote"
keyboardType="numeric"
defaultValue={getFormValue("lote")}
/>
.
.
.
<SubmitButton title="Guardar" />
</AppForm>
</ScrollView>
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: "white",
flex: 1,
justifyContent: "center",
marginHorizontal: 10,
// paddingTop: 50,
},
});
AppFormField
import React from "react";
import { useFormikContext } from "formik";
import { StyleSheet, View } from "react-native";
import AppTextInput from "../AppTextInput";
import ErrorMessage from "./ErrorMessage";
function AppFormField({ placeholder, name, width, holder, ...otherProps }) {
const { setFieldTouched, handleChange, errors, touched } = useFormikContext();
return (
<View style={styles.container}>
<AppTextInput
onBlur={() => setFieldTouched(name)}
onChangeText={handleChange(name)}
width={width}
holder={holder}
placeholder={placeholder}
{...otherProps}
/>
<ErrorMessage error={errors[name]} visible={touched[name]} />
</View>
);
}
const styles = StyleSheet.create({
container: {
marginBottom: 20,
marginHorizontal: 20,
},
});
export default AppFormField;
AppTextInput
import React from "react";
import { StyleSheet, View, TextInput, Text, Keyboard } from "react-native";
function AppTextInput({ placeholder = " ", holder, ...otherProps }) {
return (
<View style={styles.container}>
<Text style={styles.holder}>{holder}</Text>
<TextInput
style={styles.input}
placeholder={placeholder}
returnKeyLabel="Listo"
returnKeyType="done"
onSubmitEditing={Keyboard.dismiss}
{...otherProps}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: "transparent",
},
holder: {
fontSize: 20,
textAlign: "left",
color: "#000",
opacity: 0.6,
width: "100%",
height: 30,
},
input: {
fontSize: 20,
borderBottomWidth: 1,
borderColor: "#D9D5DC",
width: "100%",
},
});
export default AppTextInput;
SOLVED:
For some reason my ScrollView component had the property paddingBottom set to 500, and just by removing it, I solved the issue.
I am new with react native and when i try do this
<TextInput
style={styles.input}
onChange={(text) => setPontoValue(text)}
/>
i receive this error
TS2345: Argument of type 'NativeSyntheticEvent<TextInputChangeEventData>' is not assignable to parameter of type 'SetStateAction<undefined>'. Type 'NativeSyntheticEvent<TextInputChangeEventData>' provides no match for the signature '(prevState: undefined): undefined'.
all code is below
import React, { useState } from 'react'
import {
TextInput,
TouchableOpacity,
StyleSheet,
SafeAreaView,
Text,
View, Button,
} from 'react-native'
export default function App() {
const [pontoValue, setPontoValue] = useState()
const [dataValue, setDataValue] = useState()
return (
<SafeAreaView style={styles.container}>
<View style={styles.repositoryContainer}>
<TextInput
style={styles.input}
onChange={(text) => setPontoValue(text)}
/>
<TextInput
style={styles.input}
value={dataValue}
/>
<TouchableOpacity>
<Button
title="Calcular"
onPress={teste}>Converter
</Button>
</TouchableOpacity>
</View>
</SafeAreaView>
)
function teste() {
if (pontoValue) {
setDataValue(pontoValue.replace(/[ .]+/g, ''))
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignContent: 'center',
backgroundColor: '#7199c1',
},
repositoryContainer: {
marginBottom: 15,
marginHorizontal: 15,
backgroundColor: '#fff',
padding: 20,
},
input: {
height: 40,
padding: 5,
borderColor: 'gray',
borderWidth: 1,
},
buttonText: {
marginVertical: 11,
fontSize: 14,
fontWeight: 'bold',
color: '#fff',
backgroundColor: '#7159c1',
padding: 15,
},
})
onChange event returns an event object which has nativeEvent function which providers access to the following properties: { eventCount, target, text}
you need the text property, so you can use:
onChange={(event) => setPontoValue(event.nativeEvent.text)}
or
onChangeText={(text) => setPontoValue(text)}
I suggest you to use onChangeText prop.
onChangeText is a prop that gives you only text changes.
onChange on the other hand, passes an event.
So, try this
<TextInput
style={styles.input}
onChangeText={(text) => setPontoValue(text)}
/>
Also, always initialize your state variables.
const [pontoValue, setPontoValue] = useState('')
const [dataValue, setDataValue] = useState('')
It will reduce to chance of getting undefined errors.
Hope it works.
Right now I am trying to make a Log In Page and I've been using React Native to do so. It works perfectly fine on a web browser but when I try it on my phone, onChange doesn't seem to change the state of the password and username.
import React from 'react';
import { TextInput, View, TouchableOpacity, Text } from 'react-native';
class LogIn extends React.Component {
constructor(props){
super(props);
this.state={
username: 'John Doe',
password: 'abc123'
}
}
loginChangeHandler = (event) =>{
this.setState({[event.target.name]: event.target.value});
}
loginButtonHandler = () =>{
alert('username: '+this.state.username+ ' Password: '+this.state.password)
}
render() {
return (
<View style = {{alignItems: 'center'}}>
<TextInput name = 'username' onChange = {this.loginChangeHandler}
placeholder = 'username'
style={{ width: 200, height: 55, borderColor: 'gray', borderWidth: 1 }}
/>
<Text>{'\n'}</Text>
<TextInput name = 'password' onChange = {this.loginChangeHandler} secureTextEntry={true}
placeholder = 'password'
style={{ width: 200, height: 55, borderColor: 'gray', borderWidth: 1 }}
/>
<Text>{'\n'}</Text>
<TouchableOpacity onPress = {this.loginButtonHandler} style = {{height: 45, width: 200, justifyContent: 'center', alignItems: "center", backgroundColor: 'green'}}>
<Text style = {{fontSize: 16, color: 'white'}}>LOG IN</Text>
</TouchableOpacity>
</View>
);
}
}
export default LogIn;
To use this inside of a function you must bind the function with this object. Other thing is there isn't direct name prop for TextInput component and event.target is not returning something you expected. onChange is called with { nativeEvent: { eventCount, target, text} }, then i suggest you to use onChangeText callback. This callback is called with only the value which you are typing.
Change your code this way.
render() {
return (
<View style = {{alignItems: 'center'}}>
<TextInput name = 'username' onChangeText= {(value) => this.setState({ username : value })}
placeholder = 'username'
style={{ width: 200, height: 55, borderColor: 'gray', borderWidth: 1 }}
/>
<Text>{'\n'}</Text>
<TextInput name = 'password' onChangeText={(value) => this.setState({ password : value })} secureTextEntry={true}
placeholder = 'password'
style={{ width: 200, height: 55, borderColor: 'gray', borderWidth: 1 }}
/>
<Text>{'\n'}</Text>
<TouchableOpacity onPress = {this.loginButtonHandler.bind(this)} style = {{height: 45, width: 200, justifyContent: 'center', alignItems: "center", backgroundColor: 'green'}}>
<Text style = {{fontSize: 16, color: 'white'}}>LOG IN</Text>
</TouchableOpacity>
</View>
);
}
EDITED I am new to ReactNative and I am trying to write on my TextBoxes. However, I am not able to enter anything. I tried adding redux form for to signup screen. This is my Signup.js :
import React, { Component } from 'react';
import {StyleSheet, Text, View, StatusBar, TouchableOpacity} from 'react-native';
import {Field, reduxForm} from 'redux-form';
import Logo from '../components/Logo';
import Form from '../components/Form';
import InputText from '../components/InputText';
import {Actions} from 'react-native-router-flux';
const styles = StyleSheet.create({
container:{
backgroundColor: '#232122',
flex: 1,
alignItems: 'center',
justifyContent: 'center'
},
signupTextCont:{
flexGrow: 1,
alignItems:'flex-end',
justifyContent: 'center',
paddingVertical:16,
flexDirection:'row'
},
signupText: {
color:'rgba(255,255,255,0.7)',
fontSize:16
},
signupButton: {
color: '#FFA200',
fontSize:16,
fontWeight:'500'
},
button:{
width:300,
backgroundColor:'#FFA200',
borderRadius:25,
marginVertical:10,
paddingVertical: 13
},
buttonText:{
fontSize:16,
fontWeight:'500',
color:'#ffffff',
textAlign:'center'
},
errorText:{
color:"#FFA200",
fontSize:14,
paddingHorizontal:16,
paddingBottom: 8
}
});
class Signup extends Component<{}> {
goBack() {
Actions.pop();
}
createNewUser = () =>{
alert("Utilizador criado com sucesso!")
}
onSubmit = (values) => {
console.log(values);
}
renderTextInput = (field) => {
const {meta: {touched, error}, label, secureTextEntry, maxLength, keyboardType, placeholder, input: {onChange, ...restInput}} = field;
return(
<View>
<InputText
onChangeText={onChange}
maxLength={maxLength}
placeholder={placeholder}
keyboardType={keyboardType}
secureTextEntry={secureTextEntry}
label={label}
{...restInput} />
{touched && <Text style={styles.errorText}>{error}</Text>}
</View>
);
}
render() {
const {handleSubmit} = this.props;
return(
<View style={styles.container}>
<Logo/>
<Field
name="name"
placeholder="Insira o seu nome"
component={this.renderTextInput}/>
<Field
name="email"
placeholder="Insira o seu email"
component={this.renderTextInput}/>
<Field
name="password"
placeholder="Password"
secureTextEntry={true}
component={this.renderTextInput}/>
<TouchableOpacity style={styles.button} onPress={handleSubmit(this.onSubmit)}>
<Text style={styles.buttonText}>Signup</Text>
</TouchableOpacity>
<View style={styles.signupTextCont}>
<Text style={styles.signupText}>Ja tens uma conta?</Text>
<TouchableOpacity onPress={this.goBack}><Text style={styles.signupButton}> Entra</Text></TouchableOpacity>
</View>
</View>
)
}
}
const validate = (values) => {
const errors = {};
if(values.name){
errors.name = "Name is required"
}
if(values.email){
errors.email = "Email is required"
}
if(values.name){
errors.password = "Password is required"
}
return errors;
}
export default reduxForm({
form: "register",
validate
})(Signup)
And this is my InputText:
import PropTypes from "prop-types";
import React, {Component} from "react";
import {TextInput, Text, View, StyleSheet} from "react-native";
const propTypes = {
mapElement: PropTypes.func,
onSubmitEditing: PropTypes.func,
onChangeText: PropTypes.func,
value: PropTypes.string,
placeholder: PropTypes.string,
maxLength: PropTypes.number,
keyboardType: PropTypes.string,
secureTextEntry: PropTypes.bool,
label: PropTypes.string
};
const defaultProps = {
mapElement: (n) => {},
onSubmitEditing: () => {},
onChangeText: () => {},
value: "",
placeholder: "",
maxLength: 200,
keyboardType: "default",
secureTextEntry: false,
label: ""
};
const styles = StyleSheet.create({
inputBox: {
width:300,
backgroundColor:'rgba(255, 255,255,0.2)',
borderRadius: 25,
paddingHorizontal:16,
fontSize:16,
color:'#ffffff',
marginVertical: 10
}
});
class InputText extends Component <{}> {
render() {
const {placeholder, secureTextEntry, keyboardType, maxLength, value, onChangeText, onSubmitEditing} = this.props;
return (
<View>
<TextInput
style={styles.inputBox}
underlineColorAndroid="rgba(0,0,0,0)"
placeholder={placeholder}
placeholderTextColor="rgba(255,255,255,0.8)"
selectionColor="#999999"
secureTextEntry={secureTextEntry}
keyboardType={keyboardType}
maxLength={maxLength}
returnKeyType="next"
value={value}
onSubmitEditing={onSubmitEditing}
onChangeText={this.onChangeText} />
</View>
);
}
}
InputText.defaultProps = defaultProps;
InputText.propTypes = propTypes;
export default InputText;
I don't understand why this is happening. Please help me
<TextInput
style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
onChangeText={text => onChangeText(text)}
value={value}
/>
I think trying this method
I have this chat screen in my app where I am sending a message with the help of a button next to it and with its onPress(),
Here is the code:
import React, { Component } from "react";
import {
View,
Text,
StyleSheet,
TextInput,
Button,
Image,
TouchableOpacity,
Picker,
AsyncStorage
} from "react-native";
import axios from "axios";
import { Dropdown } from "react-native-material-dropdown";
import { Input } from "native-base";
class MessageForm extends Component {
state = {
message: "",
rc_id: this.props.rc_id,
usertype: this.props.usertype,
senderid: this.props.userid,
subject: this.props.subject
};
sendMessage = async () => {
console.log(
this.state.rc_id,
this.state.usertype,
this.state.senderid,
this.state.message,
this.state.subject
);
try {
let { data } = await axios
.post("https://tgesconnect.org/api/Communicate_class", {
userid: this.state.rc_id,
usertype: this.state.usertype,
message: this.state.message,
senderid: this.state.senderid,
subject: this.state.subject
})
.then(response => {
console.log(response.data);
this.setState({
message: ""
});
});
} catch (err) {
console.log(err);
}
};
render() {
return (
<View>
<View style={styles.container}>
<Input
style={styles.textInput}
placeholder={this.props.message}
underlineColorAndroid="transparent"
onChangeText={message => {
this.setState({ message });
}}
/>
<TouchableOpacity
style={styles.button}
onPress={() => {
this.sendMessage();
}}
>
<Image source={require("../../Assets/Images/ic_send.png")} />
</TouchableOpacity>
</View>
</View>
);
}
}
export default MessageForm;
const styles = StyleSheet.create({
container: {
display: "flex",
flexDirection: "row",
minWidth: "100%",
backgroundColor: "#eeeeee",
borderTopColor: "#cccccc",
borderTopWidth: 1,
flex: 1,
justifyContent: "flex-end"
},
textInput: {
flex: 1,
backgroundColor: "#ffffff",
height: 40,
margin: 10,
borderRadius: 5,
padding: 3
},
button: {
flexShrink: 0,
width: 40,
height: 40,
marginTop: 10,
marginRight: 10,
marginBottom: 10,
alignItems: "center",
justifyContent: "center"
},
container1: {
flex: 1,
alignItems: "center",
justifyContent: "center"
}
});
Now when I click on the Touchable icon, the textbox is not getting cleared, I don't understand why it is not happening.
I have changed the state again to have a blank text but still it is not happening.
Bind the input value with the state.
<Input
style={styles.textInput}
placeholder={this.props.message}
underlineColorAndroid="transparent"
onChangeText={message => {this.setState({ message });}}
value={this.state.message}
/>
You can use useState.
just import by import {useState} from "react";
const [text, setText] = useState("");
const onChange = (textValue) => setText(textValue);
return (
<View style={styles.container}>
<TextInput
placeholder="Item"
style={styles.text}
onChangeText={onChange}
value={text}
/>
<TouchableOpacity
style={styles.btn}
onPress={() => {
//addItem.addItem(text);
setText("");
}}
>
<Text>Add</Text>
</TouchableOpacity>
</View>
);
<TextInput
style={styles.textInput}
placeholder="Start to type.."
multiline={true}
maxLength={3000}
value={this.state.sms}
onChangeText={(sms)=>this.setState({sms})}
/>