♻ Refactor using react-hook-form

This commit is contained in:
nikolark committed 2021-10-05 23:40:11 +02:00
1 parent 1d66f1dfe3
commit a6ae37cdac
3 files changed
+114 -221

No files matched your search

+1
View File
@@ -28,6 +28,7 @@
"native-base": "^3.2.0",
"prop-types": "^15.7.2",
"react": "^17.0.2",
"react-hook-form": "^7.17.1",
"react-is": "^17.0.2",
"react-native": "0.66.0-rc.4",
"react-native-confetti": "^0.1.0",
+108 -221
View File
@@ -1,245 +1,132 @@
import React, { useState, useEffect, useRef } from 'react';
import React from 'react';
import { Container, Input, Spinner, Button, Text, Icon, Toast, FormControl } from 'native-base';
import { StyleSheet, View } from 'react-native';
import * as EmailValidator from 'email-validator';
import { useForm, Controller } from 'react-hook-form';
import theme from '../../theme';
import useUserRegister from './useUserRegister';
const FormInput = ({
control,
errors,
name,
label,
rules = {
required: true,
},
returnKeyType = 'next',
...rest
}) => {
return (
<Controller
control={control}
rules={rules}
render={({ field: { onChange, onBlur, value } }) => (
<FormControl isInvalid={errors.firstName}>
<FormControl.Label>{label}</FormControl.Label>
<Input returnKeyType={returnKeyType} onChangeText={onChange} onBlur={onBlur} value={value} {...rest} />
{errors[name] && (
<View>
<Text>kan ikke være tomt.</Text>
<Icon name="close-circle" />
</View>
)}
</FormControl>
)}
name={name}
defaultValue=""
/>
);
};
const Registerbutton = ({ isDisabled, onPress }) => (
<Button full disabled={isDisabled} onPress={onPress} style={styles.registerButton}>
<Text>Registrer meg</Text>
</Button>
);
const NonFieldErrors = ({ errors }) => {
if (Object.keys(errors).length !== 0 && 'non_field_errors' in errors) {
const err = errors.non_field_errors;
const errorFormatted = err ? err[0] : 'Kunne ikke registrere bruker, prøv igjen...';
return (
<View style={styles.errorBox}>
<Text style={styles.errorMessage}>{errorFormatted}</Text>
</View>
);
}
if (Object.keys(errors).length !== 0 && 'detail' in errors) {
const err = errors.detail;
const errorFormatted = err || 'Kunne ikke registrere bruker, prøv igjen...';
return (
<View style={styles.errorBox}>
<Text style={styles.errorMessage}>{errorFormatted}</Text>
</View>
);
}
return <View style={styles.errorBox} />;
};
const UserRegister = () => {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [email, setEmail] = useState('');
const [phoneNumber, setPhoneNumber] = useState('');
const [password, setPassword] = useState('');
const [errors, setErrors] = useState({});
const [touched, setTouched] = useState(new Set());
const { isRegisteringUser, onRegisterPress } = useUserRegister();
// TODO: email validation
// TODO: focus next field
const emailInputRef = useRef();
const lastNameInputRef = useRef();
const phoneInputRef = useRef();
const passwordInputRef = useRef();
const {
control,
handleSubmit,
formState: { errors, isDirty, isValid },
} = useForm();
const isDisabled = !isDirty || isRegisteringUser || !isValid;
const onSubmit = (data) => {
console.log(data);
// if (!canSubmitForm()) {
// Toast.show({
// text: 'Noen av feltene er ikke fylt ut riktig',
// position: 'bottom',
// buttonText: 'OK',
// duration: 1500,
// });
// return;
// }
const validateForm = (triggeredBy) => {
const values = { firstName, lastName, email, phoneNumber, password };
const freshErrors = { ...errors };
const freshTouched = new Set(touched).add(triggeredBy);
/* No empty fields */
Object.entries(values).forEach(([key, value]) => {
if (value === '') {
freshErrors[key] = 'kan ikke være tomt';
} else if (key === 'email' && !EmailValidator.validate(value)) {
freshErrors[key] = 'er ikke en gyldig e-post';
} else {
delete freshErrors[key];
}
});
setErrors(freshErrors);
setTouched(freshTouched);
};
const fieldHasError = (field) => {
return touched.has(field) && field in errors;
};
const canSubmitForm = () => {
return Object.keys(errors).length === 0;
};
// useEffect(() => {
// if (prevRegisterError !== registerError) {
// setErrors(registerError);
// }
// }, []);
const showFieldError = (field) => {
if (!fieldHasError(field)) {
return null;
}
return (
<FormControl style={styles.errorText}>
<Text style={styles.errorMessage}>{errors[field]}</Text>
</FormControl>
);
};
const firstNameInput = () => {
return (
<FormControl isInvalid={fieldHasError('firstName')}>
<FormControl.Label>Fornavn</FormControl.Label>
<Input
autoFocus={true}
returnKeyType="next"
onChangeText={(value) => {
setFirstName(value);
validateForm('firstName');
}}
onSubmitEditing={() => {
lastNameInputRef.current.focus();
}}
value={firstName}
/>
{fieldHasError('firstName') && <Icon name="close-circle" />}
</FormControl>
);
};
const lastNameInput = () => {
return (
<FormControl isInvalid={fieldHasError('lastName')}>
<FormControl.Label>Etternavn</FormControl.Label>
<Input
ref={lastNameInputRef}
returnKeyType="next"
onChangeText={(value) => {
setLastName(value);
validateForm('lastName');
}}
onSubmitEditing={() => {
emailInputRef.current.focus();
}}
value={lastName}
/>
{fieldHasError('lastName') && <Icon name="close-circle" />}
</FormControl>
);
};
const emailInput = () => {
return (
<FormControl isInvalid={fieldHasError('email')}>
<FormControl.Label>E-post</FormControl.Label>
<Input
ref={emailInputRef}
keyboardType="email-address"
autoCapitalize="none"
autoCorrect={false}
returnKeyType="next"
onChangeText={(value) => {
setEmail(value);
validateForm('email');
}}
onSubmitEditing={() => {
phoneInputRef.current.focus();
}}
value={email}
/>
{fieldHasError('email') && <Icon name="close-circle" />}
</FormControl>
);
};
const phoneNumberInput = () => {
return (
<FormControl isInvalid={fieldHasError('phoneNumber')}>
<FormControl.Label>Mobilnummer</FormControl.Label>
<Input
ref={phoneInputRef}
returnKeyType="next"
keyboardType="phone-pad"
onChangeText={(value) => {
setPhoneNumber(value);
validateForm('phoneNumber');
}}
onSubmitEditing={() => {
passwordInputRef.current.focus();
}}
value={phoneNumber}
/>
{fieldHasError('phoneNumber') && <Icon name="close-circle" />}
</FormControl>
);
};
const passwordInput = () => {
return (
<FormControl isInvalid={fieldHasError('password')}>
<FormControl.Label>Passord</FormControl.Label>
<Input
ref={passwordInputRef}
secureTextEntry={true}
autoCapitalize="none"
autoCorrect={false}
onChangeText={(value) => {
setPassword(value);
validateForm('password');
}}
onSubmitEditing={onRegisterPress}
value={password}
/>
{fieldHasError('password') && <Icon name="close-circle" />}
</FormControl>
);
};
const showNonFieldError = () => {
if (Object.keys(errors).length !== 0 && 'non_field_errors' in errors) {
const err = errors.non_field_errors;
const errorFormatted = err ? err[0] : 'Kunne ikke registrere bruker, prøv igjen...';
return (
<View style={styles.errorBox}>
<Text style={styles.errorMessage}>{errorFormatted}</Text>
</View>
);
}
if (Object.keys(errors).length !== 0 && 'detail' in errors) {
const err = errors.detail;
const errorFormatted = err || 'Kunne ikke registrere bruker, prøv igjen...';
return (
<View style={styles.errorBox}>
<Text style={styles.errorMessage}>{errorFormatted}</Text>
</View>
);
}
return <View style={styles.errorBox} />;
};
const onSubmit = () => {
if (!canSubmitForm()) {
Toast.show({
text: 'Noen av feltene er ikke fylt ut riktig',
position: 'bottom',
buttonText: 'OK',
duration: 1500,
});
return;
}
onRegisterPress(firstName, lastName, email, phoneNumber, password);
};
const registerbutton = () => {
const isDisabled = touched.size === 0 || isRegisteringUser || !canSubmitForm();
return (
<Button full disabled={isDisabled} onPress={onSubmit} style={styles.registerButton}>
<Text>Registrer meg</Text>
</Button>
);
// onRegisterPress(firstName, lastName, email, phoneNumber, password);
};
return (
<Container style={styles.container}>
<View style={styles.card}>
{firstNameInput()}
{showFieldError('firstName')}
{lastNameInput()}
{showFieldError('lastName')}
{emailInput()}
{showFieldError('email')}
{phoneNumberInput()}
{showFieldError('phoneNumber')}
{passwordInput()}
{showFieldError('password')}
{showNonFieldError()}
{registerbutton()}
<FormInput name="firstName" label="Fornavn" control={control} errors={errors} autoFocus={true} />
<FormInput name="lastName" label="Etternavn" control={control} errors={errors} />
<FormInput
name="email"
label="E-post"
control={control}
errors={errors}
keyboardType="email-address"
autoCapitalize="none"
autoCorrect={false}
/>
<FormInput name="phoneNumber" label="Mobilnummer" control={control} errors={errors} keyboardType="phone-pad" />
<FormInput
name="password"
label="Passord"
control={control}
errors={errors}
secureTextEntry={true}
autoCapitalize="none"
autoCorrect={false}
/>
<NonFieldErrors errors={errors} />
<Registerbutton isDisabled={isDisabled} onPress={handleSubmit(onSubmit)} />
{isRegisteringUser && <Spinner color="#f58220" />}
</View>
</Container>
);
};
export default UserRegister;
const styles = StyleSheet.create({
+5
View File
@@ -7495,6 +7495,11 @@ react-dom@^17.0.2:
object-assign "^4.1.1"
scheduler "^0.20.2"
react-hook-form@^7.17.1:
version "7.17.1"
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.17.1.tgz#dc257a5e34b3c353460ecdbbba5236e066cf80b1"
integrity sha512-9nQ+qKFHFpnWzQHdDh6F4Egxa8iJkue1KU921F8qqeyUVbPPjgQZDXaQyNHABEYjRh0ndjTI24GDA+lwm2lQdg==
"react-is@^16.12.0 || ^17.0.0", react-is@^17.0.1, react-is@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"