0

I am using Ionic with React. To build my forms I use react-hooks-form version 6.x.x. I defined a Yup object for validation, like this:

const validationSchema = object().shape
({
    email: string()
           .required("A mező kitöltése kötelező!")
           .email("Kérem valós e-mail címet adjon meg!"),
    password: string()
              .required("A mező kitöltése kötelező!")
              .min(8, "A jelszó hosszának legalább 8 karakternek kell lennie!"),
});

I am using this in my form like below:

export const LoginComponent: React.FC = () =>
{
    const [serverError, setServerError] = useState<any>()

    const { control, handleSubmit, errors } = useForm<LoginRequest>
    ({
        mode: "onChange",
        reValidateMode: "onSubmit",
        defaultValues:
        {
            email: "",
            password: ""
        },
        resolver: yupResolver(validationSchema)
    });

    const onSubmit = async (data: LoginRequest): Promise<void> =>
    {
        console.log(JSON.stringify(data));
    };

    return (
        <IonGrid class="ion-text-center ion-margin">
            <IonRow>
                <IonCol offset="1" size="10" ssize-sm></IonCol>
            </IonRow>
            <IonRow className="ion-align-self-center">
                <IonCol offset="1" size="10" size-sm><IonLabel class="title">BEJELENTKEZÉS</IonLabel></IonCol>
            </IonRow>
            <IonRow>
                <IonCol>
                    <form onSubmit={handleSubmit(onSubmit)}>
                        <HookFormEmailBox name="email"
                                          label="E-mail cím"
                                          control={control}
                                          errors={errors} />
                        <HookFormPasswordBox name="password"
                                             label="Jelszó"
                                             control={control}
                                             errors={errors} />
                        <IonButton expand="block" type="submit" className="ion-margin-top">
                            BEJELENTKEZÉS
                        </IonButton>
                    </form>
                </IonCol>
            </IonRow>
            <IonRow>
                <IonCol size="12">
                    {serverError && <ServerErrorComponent data={serverError}/>}
                </IonCol>
            </IonRow>
        </IonGrid>
    );
};

My HookFormEmailBox and HookFormPasswordBox components are:

import { Control, DeepMap, FieldError } from "react-hook-form";

export interface IBaseProps
{
    name: string;
    control: Control;
    errors?: DeepMap<Record<string, any>, FieldError>;
}


interface IHookFormEmailProps extends IBaseProps
{
    label: string;
}

const HookFormEmailBox: React.FC<IHookFormEmailProps> = (props: IHookFormEmailProps) =>
{
    return (
        <React.Fragment>
            <IonItem>
                {
                props.label &&
                <IonLabel position="floating">{props.label}</IonLabel>
                }
                <Controller as=
                            {
                                <IonInput aria-invalid={props.errors && props.errors[props.name] ? "true" : "false"}
                                          aria-describedby={`${props.name}Error`}
                                          type="email"/>
                            }
                            name={props.name}
                            control={props.control}
                            onChangeName="onIonChange">
                </Controller>
            </IonItem>
            {
                props.errors && props.errors[props.name] &&
                (
                    <IonText color="danger" className="ion-padding-start">
                        <small>
                            <span role="alert" id={`${props.name}Error`}>
                                {props.errors[props.name].message}
                            </span>
                        </small>
                    </IonText>
                )
            }
        </React.Fragment>
    );
}

export default HookFormEmailBox;

export interface IHookFormPasswordProps extends IBaseProps
{
    label: string;
}

const HookFormPasswordBox: React.FC<IHookFormPasswordProps> = (props: IHookFormPasswordProps) =>
{
    return (
        <React.Fragment>
            <IonItem>
                {
                props.label &&
                <IonLabel position="floating">{props.label}</IonLabel>
                }
                <Controller as=
                            {
                                <IonInput aria-invalid={props.errors && props.errors[props.name] ? "true" : "false"}
                                          aria-describedby={`${props.name}Error`}
                                          type="password"/>
                            }
                            name={props.name}
                            control={props.control}
                            onChangeName="onIonChange">
                </Controller>
            </IonItem>
            {
                props.errors && props.errors[props.name] &&
                (
                    <IonText color="danger" className="ion-padding-start">
                        <small>
                            <span role="alert" id={`${props.name}Error`}>
                                {props.errors[props.name].message}
                            </span>
                        </small>
                    </IonText>
                )
            }
        </React.Fragment>
    );
}

export default HookFormPasswordBox;

Now my problem is, that my form validates the required rule, but not the next one, not for email, not for password. I am using the following packages:

"@hookform/resolvers": "^1.3.2", "react-hook-form": "^6.14.1", "yup": "^0.32.8" "@types/yup": "^0.29.11"

As musch as I can see, the react-hook-forms library always uses the default value, it never updates the state.

thnx

Wasyster
  • 2,279
  • 4
  • 26
  • 58

1 Answers1

0

So I figured out, what was changed, and we need to modify our Input components like this:

import { IonItem, IonLabel, IonInput, IonText } from "@ionic/react";
import React from "react";
import { Controller } from "react-hook-form";
import { InputType } from "../Types/InputType";
import { IBaseProps } from "../Interfaces/BaseProps";
import { InputValueType } from "./../Types/InputValueType";

export interface IHookFormTextBoxProps extends IBaseProps
{
    label: string;
    type: InputType;
    value?: InputValueType
}

const HookFormTextBox: React.FC<IHookFormTextBoxProps> = (props: IHookFormTextBoxProps) =>
{
    return (
        <React.Fragment>
            <IonItem>
                {
                props.label &&
                <IonLabel position="floating">{props.label}</IonLabel>
                }
                <Controller render={ ({ value, onChange, onBlur }) =>
                            (
                                <IonInput aria-invalid={props.errors && props.errors[props.name] ? "true" : "false"}
                                          aria-describedby={`${props.name}Error`}
                                          type={props.type}
                                          onIonChange={onChange}
                                          onBlur={onBlur}
                                          value={value} />
                            )}
                            defaultValue={props.value ? props.value : ""}
                            name={props.name}
                            control={props.control}
                            onChangeName="onIonBlur">
                </Controller>
            </IonItem>
            {
                props.errors && props.errors[props.name] &&
                (
                    <IonText color="danger" className="ion-padding-start">
                        <small>
                            <span role="alert" id={`${props.name}Error`}>
                                {props.errors[props.name].message}
                            </span>
                        </small>
                    </IonText>
                )
            }
        </React.Fragment>
    );
}

export default HookFormTextBox;
Wasyster
  • 2,279
  • 4
  • 26
  • 58