-1
Staff I am developing an app and using the unform
of Rocketseat for form validation.
But when trying to create a validation error by displaying the component border in red if it is empty, the error returns on the signIn but when I try to 'set' him by formRef
he is not sending and ends up returning to the input as if he had no mistake. Someone could help me, I am missing something.
The Focused is working right, the problem is in error when set by formRef formRef.current?.setErrors(errors);
When I get that back useField in input it does not return the error const { registerField, defaultValue = '', fieldName, error } = useField(name);
Signin
interface SignInFormData {
email_user: string;
password_user: string;
}
const SignIn: React.FC = () => {
const formRef = useRef<FormHandles>(null);
const passwordInputRef = useRef<TextInput>(null);
const navigation = useNavigation();
const handleSignIn = useCallback(async (data: SignInFormData) => {
try {
formRef.current?.setErrors({});
const schema = Yup.object().shape({
email_user: Yup.string()
.required('E-mail obrigatório')
.email('Digite um e-mail válido'),
password_user: Yup.string().required('Senha obrigatória'),
});
await schema.validate(data, {
abortEarly: false,
});
} catch (err) {
if (err instanceof Yup.ValidationError) {
const errors = getValidationErrors(err);
formRef.current?.setErrors(errors);
return;
}
Alert.alert(
'Erro na Autenticação',
'Ocorrou um erro ao fazer login, cheque as credenciais.',
);
}
}, []);
return (
<>
<KeyboardAvoidingView
style={{ flex: 1 }}
behavior={Platform.OS === 'ios' ? 'padding' : undefined}
enabled
>
<ScrollView
keyboardShouldPersistTaps="handled"
contentContainerStyle={{ flex: 1 }}
>
<Container>
<Image source={logoImg} />
<View>
<Title>Faça seu Logon</Title>
</View>
<Form ref={formRef} onSubmit={handleSignIn}>
<Input
autoCorrect={false}
autoCapitalize="none"
keyboardType="email-address"
name="email"
icon="mail"
placeholder="E-mail"
returnKeyType="next"
onSubmitEditing={() => {
passwordInputRef.current?.focus();
}}
/>
<Input
ref={passwordInputRef}
name="password"
icon="lock"
placeholder="Senha"
secureTextEntry
returnKeyType="send"
onSubmitEditing={() => {
formRef.current?.submitForm();
}}
/>
<Button
onPress={() => {
formRef.current?.submitForm();
}}
>
Entrar
</Button>
</Form>
<ForgotPassword onPress={() => ({})}>
<ForgotPasswordText>Esqueci minha senha</ForgotPasswordText>
</ForgotPassword>
</Container>
</ScrollView>
</KeyboardAvoidingView>
<CreateAccountButton onPress={() => navigation.navigate('SignUp')}>
<Icon name="log-in" size={20} color="#e4a608" />
<CreateAccountButtonText>Criar conta</CreateAccountButtonText>
</CreateAccountButton>
</>
);
};
export default SignIn;
Input
interface InputProps extends TextInputProps {
name: string;
icon: string;
}
interface InputValueReference {
value: string;
}
interface InputRef {
focus(): void;
}
const Input: React.ForwardRefRenderFunction<InputRef, InputProps> = (
{ name, icon, ...rest },
ref,
) => {
const inputElementRef = useRef<any>(null);
const { registerField, defaultValue = '', fieldName, error } = useField(name);
const inputValueRef = useRef<InputValueReference>({ value: defaultValue });
const [isFocused, setIsFocused] = useState(false);
const [isFilled, setIsFilled] = useState(false);
const handleInputFocus = useCallback(() => {
setIsFocused(true);
}, []);
const handleInputBlur = useCallback(() => {
setIsFocused(false);
setIsFilled(!!inputValueRef.current.value);
}, []);
useImperativeHandle(ref, () => ({
focus() {
inputElementRef.current.focus();
},
}));
useEffect(() => {
registerField<string>({
name: fieldName,
ref: inputValueRef.current,
path: 'value',
});
}, [fieldName, registerField]);
return (
<Container isFocused={isFocused} isErrored={!!error}>
<Icon
name={icon}
size={20}
color={isFocused || isFilled ? '#e4a608' : '#666360'}
/>
<TextInput
ref={inputElementRef}
keyboardAppearance="dark"
placeholderTextColor="#666360"
defaultValue={defaultValue}
onFocus={handleInputFocus}
onBlur={handleInputBlur}
onChangeText={(value) => {
inputValueRef.current.value = value;
}}
{...rest}
/>
</Container>
);
};
export default forwardRef(Input);
CSS Input
interface ContainerProps {
isFocused: boolean;
isErrored: boolean;
}
export const Container = styled.View<ContainerProps>`
width: 100%;
height: 60px;
padding: 0 16px;
background: #ffffff;
border-radius: 10px;
margin-bottom: 8px;
border-width: 2px;
border-color: #ffffff;
flex-direction: row;
align-items: center;
${(props) =>
props.isErrored &&
css`
border-color: #ff0000;
`}
${(props) =>
props.isFocused &&
css`
border-color: #e4a608;
`}
`;