I have 2 user text inputs called Search Location and Coordinates. I'm trying to use a checkbox when selected allows search location to be edited and the coordinates input be disabled and vice versa when the checkbox is not selected.
When i first run the code, i can edit Search Location and Coordinates is disabled. When i select the checkbox the text input works fine, Search Location is disabled and Coordinates is editable. However, when i try to unselect the checkbox, Search Location is still disabled and Coordinates can still be edited.
I have tried using useEffect but im not too familiar with this nor do i know if this is the correct approach. I am using react hook forms for user inputs and i use react native elements for checkboxes.
Code:
export default function UserInput({ navigation }) {
const { handleSubmit, control } = useForm();
const [checkbox, setCheck] = useState(false);
const [edit1, setEdit1] = useState(true);
const [edit2, setEdit2] = useState(false);
const onSelect = () => {
if (!checkbox) {
setEdit1(false);
setEdit2(true);
}
setCheck(!checkbox);
};
return (
<View style={styles.formContainer}>
<Text style={styles.text}>Distance(km)</Text>
<Controller
name="distance"
control={control}
rules={{
required: true,
}}
render={({ field: { onChange, value } }) => (
<TextInput
placeholder="Enter your Distance"
style={styles.input}
onChangeText={onChange}
value={value}
/>
)}
/>
<Text style={styles.text}>Search Location</Text>
<Controller
name="searchLocation"
control={control}
rules={{
required: true,
}}
render={({ field: { onChange, value } }) => (
<TextInput
placeholder="Enter your Coordinates"
style={styles.input}
onChangeText={onChange}
value={value}
editable={edit1}
/>
)}
/>
<CheckBox
center
title="Current Location"
checked={checkbox}
onPress={onSelect}
/>
<Text style={styles.text}>Coordinates</Text>
<Controller
name="coordinates"
control={control}
rules={{
required: true,
}}
render={({ field: { onChange, value } }) => (
<TextInput
placeholder="Enter your Coordinates"
style={styles.input}
onChangeText={onChange}
value={value}
editable={edit2}
/>
)}
/>
</View>
);
}
Try this one
const onSelect = () => {
if (!checkbox) {
setEdit1(false);
setEdit2(true);
} else {
setEdit1(true);
setEdit2(false);
}
setCheck(!checkbox);
};
Related
I want to save the values from all input fields to getdata(), but I am getting undefined value
export default function Signupfor(props) {
// const phoneInput = useRef < PhoneInput > null;
const [text, setTextname] = useState();
function getdata() {
console.log('dsd');
console.log(text);
}
const {userInfo, log} = props?.route?.params;
console.log(log.name);
return (
<View style={styles.prheight}>
<View style={styles.form}>
<Text style={styles.r}>One Last Step</Text>
<TextInput
style={styles.forminput}
label="Name"
value={userInfo.user.name}
onChangeText={text => setTextname(text)}
/>
<TextInput
style={styles.forminput}
label="Email"
value={userInfo.user.email}
onChangeText={text => setTextemail(text)}
/>
<TextInput
style={styles.forminput}
label="Whatsapp Number"
keyboardType="numeric"
value={userInfo.user.number}
onChangeText={text => setTextnumber(text)}
// value={this.state.myNumber}
maxLength={10} //setting limit of input
/>
</View>
<View style={styles.buttonw}>
<Button color="#7743DB" title="Lets Go" onPress={() => getdata()} />
</View>
</View>
);
}
Here, name and email should not be able to be edited. I want to pass the value from value={userInfo.user.name} to the getdata()
you can use formik package for making form in react native
Installation
yarn add formik
Usage
import { Formik } from "formik";
export default function Signupfor(props) {
const { userInfo, log } = props?.route?.params;
console.log(log.name);
return (
<Formik
initialValues={{
name: userInfo.user.name,
email: userInfo.user.email,
number: userInfo.user.number,
}}
onSubmit={async (values, actions) => {
try {
console.log("name", values.name);
console.log("phone", values.number);
const params = {
full_name: values.name,
email: values.email,
phone_number: values.number,
};
} catch (error) {
let message = error.message;
console.log(message)
} finally {
actions.setSubmitting(false);
}
}}
>
{({
handleChange,
setFieldValue,
handleSubmit,
values,
errors,
touched,
isSubmitting,
}) => (
<View style={styles.prheight}>
<View style={styles.form}>
<Text style={styles.r}>One Last Step</Text>
<TextInput
style={styles.forminput}
label="Name"
value={values.name}
onChangeText={handleChange("name")}
/>
<TextInput
style={styles.forminput}
label="Email"
value={values.email}
onChangeText={handleChange("email")}
/>
<TextInput
style={styles.forminput}
label="Whatsapp Number"
keyboardType="numeric"
value={values.number}
onChangeText={handleChange("number")}
// value={this.state.myNumber}
maxLength={10} //setting limit of input
/>
</View>
<View style={styles.buttonw}>
<Button
color="#7743DB"
title="Lets Go"
onPress={() => handleSubmit()}
/>
</View>
</View>
)}
</Formik>
);
}
Your original method doesn't populate the state unless you edit the text input field, this is because your initialState doesn't have a value to start with. so firing getData() is reading empty state if the fields havent been changed.
onChangeText={text => setTextname(text)}
Only fire if you edit the textInput field.
Also I think you might be missing props, so first check if you are getting the correct data from props by logging it.
Once you have confirmed the props are available.
Set the initialState for name to userInfo.user.name
const { userInfo } = props?.route?.params;
const [name, setName] = useState(userInfo.user.name);
Then pass the state name to your TextInput and it should populate the value by reading from state.
return (
<>
<TextInput
placeholder="name"
value={name}
onChangeText={(text) => setName(text)}
/>
<Button title="Submit" onPress={() => getData()} />
</>
)
Make sure to create states for any additional values you wish to save.
const [name, setName] = useState(userInfo.user.name);
const [email, setEmail] = useState(userInfo.user.email);
You can use a library like https://react-hook-form.com to check an example with react native on video.
Or you can right it yourself, in the example below any time you need access to input values you can read it from text and number
const UselessTextInput = () => {
const [text, onChangeText] = useState("Useless Text");
const [number, onChangeNumber] = useState(null);
return (
<SafeAreaView>
<TextInput
style={styles.input}
onChangeText={onChangeText}
value={text}
/>
<TextInput
style={styles.input}
onChangeText={onChangeNumber}
value={number}
placeholder="useless placeholder"
keyboardType="numeric"
/>
</SafeAreaView>
);
};
You can do something like this!!
export default function Signupfor(props) {
const {userInfo, log} = props?.route?.params;
const [name, setName] = useState(userInfo?.user?.name);
const [phone, setPhone] = useState(userInfo?.user?.number);
function getdata() {
console.log("name",name)
console.log("phone",phone)
}
return (
<View style={styles.prheight}>
<View style={styles.form}>
<Text style={styles.r}>One Last Step</Text>
<TextInput
style={styles.forminput}
label="Name"
// this value must be same with useState
value={name}
onChangeText={text => setName(text)}
/>
<TextInput
style={styles.forminput}
label="Mobile"
value={phone}
onChangeText={text => setPhone(text)}
/>
</View>
<View style={styles.buttonw}>
<Button color="#7743DB" title="Lets Go" onPress={() => getdata()} />
</View>
</View>
);
}
Same goes for email.
I design a page to input account and password.
And I create a function component "LabelPwd" to password.
I want focus on password field after user submit account.
But nothing happened after submit account by the code below.
Can anyone provide some advise?
Main Page:
const [pwdFocused, setPwdFocused] = useState(false);
return (
<Controller
render={({ onChange, value }) => (
<LabelInput
error={errors ? errors.userId : errors}
label={t('common.userId')}
value={value}
autoFocus
onSubmitEditing={setPwdFocused(true)}
/>
)}
/>
<Controller
render={({ onChange, value }) => (
<LabelPwd
error={errors.password}
onChangeText={v => onChange(v)}
value={value}
setFocused={pwdFocused}
/>
)}
/>
);
LabelPwd
export default function LabelPwd({ value, onChangeText, error, setFocused }) {
const [pwdIcon, setPwdIcon] = useState('eye-off');
const pwdRef = useRef();
useEffect(() => {
//Seems didn't trigger here.
if (setFocused && pwdRef.current) {
pwdRef.current.focus();
}
}, [setFocused]);
function onPressPwdEye() {
if (pwdIcon === 'eye-off') {
setPwdIcon('eye');
setSecureMode(false);
} else {
setPwdIcon('eye-off');
setSecureMode(true);
}
}
return (
<>
<Input
errorMessage={error ? t('common.isRequired') : null}
label={t('common.password')}
rightIcon={{ type: 'feather', name: pwdIcon, size: 24, color: 'gray', onPress: onPressPwdEye }}
secureTextEntry={secureMode}
value={value}
onChangeText={onChangeText}
ref={pwdRef}
/>
</>
);
}
I have a question about how to pass props for one screen to another, and display the props using listItem from "React Native Elements".
First i will paste the code of the screen with the "Add Friend" form:
const addFriend = ({ navigation }) => {
const [friend, setFriend] = useState('');
const [phone, setPhone] = useState('');
return (
<View style={styles.container}>
<Input
placeholder='Friend Name'
onChangeText={friend => setFriend(friend)}
leftIcon={
<Icon
name='user'
size={24}
color='grey'
/>
}
/>
<Input
onChangeText={phone => setPhone(phone)}
placeholder='Friend Phone Number'
leftIcon={
<Icon
name='phone'
size={24}
color='grey'
/>
}
/>
<Button
title="Add Friend"
onPress={() => {
navigation.navigate('FriendList', { friend, phone })
}}
/>
</View>
);
}
Second, i will paste the screen that is suppose to show the list of friends i want to add, here i cant find the way to pass the props from the screen above, to the list:
const list = [
{
name: '',
avatar_url: 'https://s3.amazonaws.com/uifaces/faces/twitter/ladylexy/128.jpg',
subtitle: ''
}
]
const FriendList = ({ route, navigation }) => {
const { friend } = route.params;
const { phone } = route.params;
return (
<View style={styles.container}>
list.map((l, i) => (
<ListItem
key={i}
leftAvatar={{ source: { uri: l.avatar_url } }}
title={l.name}
subtitle={l.subtitle}
bottomDivider
/>
))
}
{/* <Text>{JSON.stringify(friend)} {JSON.stringify(phone)}</Text> */}
</View>
);
}
You can find your parameters that you pass to your second screen in
let {friend, phone} = this.props.navigation.state.params;
The button's onPress function is called when neither of text fields above are filled. Otherwise, I press the button and nothing happens. I've tried change the onPress to onPress={this.handleSubmit()} but then the function is called before any data is in the TextInput's and an error is thrown. I've also tried using the tcomb-form-native package, but the problem persists. What do I need to change to get the handleSubmit function to be called when the text inputs are filled?
handleSubmit = () => {
console.log('handle submit')
}
render() {
return (
<View style={styles.container}>
<TextInput
style={{height: 40}}
placeholder="Your name"
onChangeText={userName => this.setState({userName})}
/>
<TextInput
style={{height: 40}}
placeholder="other name"
onChangeText={otherName => this.setState({otherName})}
/>
<Button
title="Name"
onPress={this.handleSubmit}
/>
</View>
);
}
Have you tried using
e.preventDefault()
?
handleSubmit = (e) => {
e.preventDefault()
console.log('handle submit')
}
constructor(props){
super(props);
this.state = {
userName: '',
otherName: ''
};
}
handleSubmit = () => {
// Check if any of them is empty then do nothing
if(!this.state.otherName || !this.state.userName){return;}
console.log('handle submit');
}
render() {
return (
<View style={styles.container}>
<TextInput
style={{height: 40}}
placeholder="Your name"
onChangeText={userName => this.setState({userName})}
/>
<TextInput
style={{height: 40}}
placeholder="other name"
onChangeText={otherName => this.setState({otherName})}
/>
<Button
title="Name"
onPress={this.handleSubmit}
/>
</View>
);
}
I'm having a form in my application where I want the user to be able to go to the next TextInput by clicking the "Next" return button.
My Input component:
export default class Input extends Component {
focusNextField = (nextField) => {
console.log('NEXT FIELD:', nextField);
this.refs[nextField].focus();
}
render() {
var keyboardType = this.props.keyboardType || 'default';
var style = [styles.textInput, this.props.style];
if (this.props.hasError) style.push(styles.error);
return (
<View style={styles.textInputContainer}>
<TextInput
placeholder={this.props.placeholder}
onChangeText={this.props.onChangeText}
style={style}
blurOnSubmit={false}
ref={this.props.reference}
returnKeyType= {this.props.returnType}
onSubmitEditing={() => this.focusNextField(this.props.fieldRef)}
secureTextEntry={this.props.isPassword}
value={this.props.value}
keyboardType={keyboardType}
underlineColorAndroid="transparent" />
{this.props.hasError && this.props.errorMessage ? <Text style={{ color: 'red' }}>{this.props.errorMessage}</Text> : null}
</View>
);
}
}
And how it is used:
<Input onChangeText={(email) => this.setState({ email })} value={this.state.email} returnType={"next"} reference={'1'} fieldRef={'2'} keyboardType="email-address" />
<Text style={{ color: '#fff', marginTop: 10, }}>Password</Text>
<Input onChangeText={(password) => this.setState({ password })} value={this.state.password} returnType={"done"}
reference={'2'} fieldRef={'2'} isPassword={true} />
But I get the error:
undefined is not an object (evaluating _this.refs[nextField].focus)
Not sure if you are still trying to do this but for anyone else who has the problem, please do the following :
Add this code to your imports (anywhere in your imports)
import { findNodeHandle } from 'react-native';
import TextInputState from 'react-native/lib/TextInputState';
export function focusTextInput(node) {
try {
TextInputState.focusTextInput(findNodeHandle(node));
} catch(e) {
console.log("Couldn't focus text input: ", e.message)
}
};
Add the following lines to your constructor
this.focusNextField = this.focusNextField.bind(this);
this.inputs = {};
Add the following function to your class
focusNextField(id) {
this.inputs[id].focus();
}
Edit your TextInput as follow :
<TextInput
onSubmitEditing={() => {this.focusNextField('two');}}
ref={ input => {this.inputs['one'] = input;}}
/>
<TextInput
onSubmitEditing={() => {this.focusNextField('three');}}
ref={ input => {this.inputs['two'] = input;}}
/>
....
Here is the source of that answer
Worked in 0.45 for me.