I’ve made a Form component for handling signup/login now i want to handle add details and add facts screen using this form component now the problem is that the input fields of both login/signup and details are different.
I thinking of passing custom Input component for both these screens for handling different inputs styles but again problem is the props which I’ll be getting in those forms is available when i map an array of form fields, what should be the approach??
My Login screen
My Expected Details Screen`
My Forms Component
import {memo, useState} from 'react';
import {Controller, useForm} from 'react-hook-form';
import {
Keyboard,
KeyboardAvoidingView,
StyleSheet,
Text,
TouchableOpacity,
TouchableWithoutFeedback,
View,
} from 'react-native';
import Input from './Input';
import {colors} from '../../constants/colors';
import Button from './Button';
import DatePickerComponent from './DatePickerComponent';
const Form = ({
onAuthenticate,
changeMode,
formdata,
notSignin = false,
onAdd,
}) => {
const [mode, setMode] = useState(true);
const [date, setDate] = useState(new Date());
const {
control,
handleSubmit,
reset,
formState: {errors},
} = useForm({
defaultValues: {
firstName: '',
lastName: '',
// email: '[email protected]',
// password: 'pass123',
email: '',
password: '',
confirmPassword: '',
author: '',
quote: '',
fact: '',
bio: '',
description: '',
},
});
const onPress = mode => {
reset();
changeMode(mode);
};
const onSubmit = data => {
const {email, password} = data;
onAuthenticate({email, password});
reset();
};
const confirmHandler = date => {
setDate(date);
};
const onAddHandler = data => {
const {author, quote, fact, bio, description} = data;
onAdd({
author: author,
quote: quote,
fact: fact,
bio: bio,
description: description,
date: date.toISOString().slice(0, 10),
});
reset();
};
return (
<KeyboardAvoidingView style={styles.root}>
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={styles.formContainer}>
{formdata?.map(item => (
<>
{item.name !== 'date' && (
<Input
key={item.name}
Controller={Controller}
errors={errors}
item={item}
control={control}
forgot={item.name === 'password' ? true : false}
/>
)}
{item.name === 'date' && (
<DatePickerComponent
key={item.name}
Controller={Controller}
errors={errors}
item={item}
control={control}
date={date}
onConfirm={confirmHandler}
setDate={setDate}
/>
)}
</>
))}
<View style={styles.container}>
{notSignin && (
<Button
additionalStyles={styles.additionalStyles}
onPress={handleSubmit(onAddHandler)}>
Add Facts
</Button>
)}
{!notSignin && (
<Button
additionalStyles={styles.additionalStyles}
onPress={handleSubmit(onSubmit)}>
{formdata?.length === 2 ? 'Login' : 'Signup'}
</Button>
)}
{/* <Button
mode="light"
additionalStyles={styles.additionalStyles}
onPress={() => {
reset();
}}>
Reset
</Button> */}
</View>
{!notSignin && (
<>
{formdata?.length === 2 && (
<Text
style={styles.register}
onPress={() => {
onPress('signup');
}}>
Register User
</Text>
)}
{formdata?.length !== 2 && (
<Text style={styles.register} onPress={() => onPress('login')}>
{' '}
Login{' '}
</Text>
)}
</>
)}
<TouchableOpacity onPress={() => {}}>
<Text style={styles.register}>Forgot Password</Text>
</TouchableOpacity>
</View>
</TouchableWithoutFeedback>
</KeyboardAvoidingView>
);
};
const styles = StyleSheet.create({
formContainer: {
backgroundColor: 'white',
flex: 1,
alignItems: 'center',
justifyContent: 'flex-start',
marginTop: 80,
width: '100%',
},
root: {
backgroundColor: 'white',
flex: 1,
alignItems: 'center',
justifyContent: 'center',
borderWidth: 1,
},
additionalStyles: {
// width: 120,
// height: 50,
marginVertical: 40,
},
register: {
fontFamily: 'DMSansBold',
marginTop: 30,
color: colors.paleYellow,
fontSize: 17,
},
container: {flexDirection: 'row'},
login: {fontFamily: 'DMSansBold', color: 'black'},
already: {fontFamily: 'DMSansRegular', color: colors.grey200},
create: {fontFamily: 'DMSansBold', color: 'black'},
});
export default memo(Form);
My InputComponent for login/signup
import {useEffect, useState} from 'react';
import {
Dimensions,
Image,
TextInput,
View,
Text,
Pressable,
StyleSheet,
} from 'react-native';
import {colors} from '../../constants/colors';
const {height, width} = Dimensions.get('screen');
const Input = ({
Controller,
control,
item,
errors,
open = false,
date = null,
}) => {
const [error, setError] = useState({});
useEffect(() => {
setError(errors);
}, [errors]);
let borderColor = colors.paleYellow;
let tintColor = colors.paleYellow;
if (error[item?.name]) {
borderColor = 'red';
tintColor = 'red';
}
// console.log('date from date picker--', date?.toISOString().slice(0, 10));
if (item?.name === 'date') {
return (
<Controller
control={control}
rules={item?.rules}
render={({field: {}}) => (
<View
style={{justifyContent: 'flex-start', backgroundColor: 'white'}}>
<Pressable
onPress={open}
style={[styles.container, {borderColor: borderColor}]}>
<Image
source={item.icon}
style={[styles.icon, {tintColor: tintColor}]}
resizeMode="contain"
/>
<Text>{date?.toISOString().slice(0, 10)}</Text>
</Pressable>
{error[item.name] && (
<Text
style={{
color: 'red',
paddingHorizontal: 20,
}}>
{error[item.name]?.message}
</Text>
)}
</View>
)}
name={item.name}
/>
);
}
return (
<Controller
control={control}
rules={item?.rules}
render={({field: {onChange, value}}) => (
<View
style={[{justifyContent: 'flex-start', backgroundColor: 'white'}]}>
<View
style={[
{
width: width * 0.73,
marginVertical: 10,
// padding: 5,
height: height * 0.06,
borderBottomWidth: 1,
flexDirection: 'row',
alignItems: 'center',
},
{borderColor: borderColor},
]}>
{/* <Image
source={item.icon}
style={{
height: 30,
width: 30,
marginHorizontal: 5,
tintColor: tintColor,
}}
resizeMode="contain"
/> */}
<TextInput
placeholderTextColor={error[item?.name] ? 'red' : colors.grey200}
placeholder={item?.placeholder}
style={{color: colors.black}}
onChangeText={onChange}
value={value}
/>
</View>
{error[item.name] && (
<Text
style={{
color: 'red',
paddingHorizontal: 20,
}}>
{error[item.name]?.message}
</Text>
)}
</View>
)}
name={item.name}
/>
);
};
const styles = StyleSheet.create({
icon: {
height: 30,
width: 30,
marginHorizontal: 5,
},
container: {
width: width * 0.73,
margin: 10,
padding: 5,
height: height * 0.06,
borderRadius: 30,
borderWidth: 1,
flexDirection: 'row',
alignItems: 'center',
},
});
export default Input;
Mukutmani Das is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.