react-native-mask-input
react-native-mask-input copied to clipboard
Doesn't work with react-hook-form (RHF) Controller inputs
The library doesn't work with with react-hook-form (RHF) Controller inputs. I make a lot of tests and the best solution is use a default useState from React. That is my code with RHF:
Perhaps in a future i go up a pull request to fix this.
import React, { useEffect, useState } from 'react';
import { Image, ScrollView, Text, View } from 'react-native';
import {
Button,
PaperProvider,
RadioButton,
useTheme,
} from 'react-native-paper';
import { Input } from '../../components/Input';
import logoSrc from '../../../assets/logo.png';
import { StatusBar } from 'expo-status-bar';
import { BloodTypes } from '../../types/BloodTypes';
import { Radio } from '../../components/Radio';
import { zodResolver } from '@hookform/resolvers/zod';
import { Controller, useForm } from 'react-hook-form';
import { z } from 'zod';
import { Link } from '@react-navigation/native';
import { cep as cepPromise } from 'cep-promise';
import { Masks, useMaskedInputProps } from 'react-native-mask-input';
const SignIn = () => {
const [isLoading, setIsLoading] = useState(false);
const createUserFormSchema = z.object({
email: z
.string()
.email('Formato de e-mail inválido')
.min(1, 'Campo obrigatório'),
password: z.string().min(6, 'A senha precisa de no mÃnimo 6 caracteres'),
name: z.string().min(1, 'Campo obrigatório'),
bloodType: z
.enum(['A+', 'A-', 'B+', 'B-', 'AB+', 'AB-', 'O+', 'O-'])
.default('A+'),
userType: z.enum(['doador', 'necessita']).default('doador'),
cep: z.string(),
});
const {
control,
handleSubmit,
formState: { errors },
getValues,
setValue,
} = useForm({
resolver: zodResolver(createUserFormSchema),
defaultValues: {
name: '',
password: '',
email: '',
bloodType: 'A+',
userType: 'doador',
cep: '',
},
});
const appTheme = useTheme();
const cepMask = [/\d/, /\d/, /\d/, /\d/, /\d/, '-', /\d/, /\d/, /\d/];
const cepMaskedInputProps = useMaskedInputProps({
value: getValues('cep'),
onChangeText: (masked, unmasked, obfuscated) => setValue('cep', unmasked),
mask: cepMask,
});
const createUser = (data: any) => {
console.log(data);
};
return (
<ScrollView
contentContainerStyle={{
width: '100%',
paddingTop: 80,
paddingBottom: 40,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: '#200c10',
}}
>
<Image source={logoSrc} className="w-80 h-40" resizeMode="contain" />
<View className="flex gap-4 px-8">
<View>
<Controller
control={control}
rules={{
required: true,
}}
render={({ field: { onChange, onBlur, value } }) => (
<Input onBlur={onBlur} label="CEP" {...cepMaskedInputProps} />
)}
name="cep"
/>
</View>
<Button
className="w-80"
mode="outlined"
loading={isLoading}
onPress={handleSubmit(createUser)}
>
{!isLoading && 'CRIAR'}
</Button>
<Link to={{ screen: 'Login' }}>
<Button className="w-80" mode="outlined">
VOLTAR
</Button>
</Link>
</View>
<StatusBar style="light" translucent backgroundColor="#200c10" />
</ScrollView>
);
};
export default SignIn;
You have to pass onChange
and value
props to your input
<Controller
control={control}
rules={{
required: true,
}}
render={({ field: { onChange, onBlur, value } }) => (
<Input onBlur={onBlur} onChange={onChange} value={value} label="CEP" {...cepMaskedInputProps} />
)}
name="cep"
/>
I forgot to write on GitHub code but I'm sure I typed
@soaresgus I don't know if you get it or not, but you could use the useController
from react-hooks-form
.
const { control } = useForm<FormData>();
const {field: fieldPhoneNumber} = useController<FormData>({
name: 'phoneNumber',
control,
});
const maskedInputProps = useMaskedInputProps({
value: fieldPhoneNumber.value,
onChangeText: fieldPhoneNumber.onChange,
mask: Masks.BRL_PHONE,
});
<Controller
control={control}
name="phoneNumber"
render={({field, fieldState}) => (
<TextInput
{...maskedInputProps}
/>
)}
/>