首页 > 解决方案 > Yup.mixed() 验证未验证

问题描述

我有一个使用 react-hooks-form 的表单,我为我制作了一些组件,例如文本框、文本区域、选择……这些都是受控组件。现在在我的表单中,我使用 Yup 进行验证,并且有一点它不起作用。在我的表单中,我有一个动态输入类型(queryParam),它根据组选择的值而变化,它可以是文本框或选择。当 group 为 1 时,不需要queryParam,但如果 group 的值大于 1 则显示字段,我需要输入queryParam的值,但它没有验证,我无法按下按钮。queryParam可以是来自文本框的文本,也可以是来自 select 的字符串形式的数字。

我的验证模式:

import * as Yup from "yup";

export const validationSchema = Yup.object().shape
({
      text: Yup
            .string()
            .required()
            .max(2048, "Az üzenet szövege túl hosszú,"),
      groupID: Yup
              .number()
              .required(),
      queryParam: Yup
                 .string()
                 .when("groupID",
                 {
                        /*** THIS PART NOT WORKING ***/
                        is: (groupID: number) => groupID > 1,
                        then: Yup.mixed()
                                 .required("Kötelező mező.")
                  }),
      isVoteType: Yup
                 .boolean(),
      positiveAnswer: Yup
                      .string()
                      .when("isVoteType",
                      {
                              is: (isVoteType: boolean) => isVoteType,
                              then: Yup.string()
                                       .required("Kötelező mező.")
                      }),
      negativeAnswer: Yup
                      .string()
                      .when("isVoteType",
                      {
                              is: (isVoteType: boolean) => isVoteType,
                              then: Yup.string()
                                       .required("Kötelező mező.")
                      })
});

我的表单组件:

import React, { useEffect, useState } from "react";
import { IonButton, IonCol, IonContent, IonGrid, IonPage, IonRow } from "@ionic/react";
import Footer from "src/pages/shared/footer/footer";
import Header from "src/pages/shared/header/header";
import { IMessageRequest } from "./../../../../modell/request/IMessageRequest";
import { useForm } from "react-hook-form";
import { yupResolver } from "@hookform/resolvers/dist/yup";
import { validationSchema } from "./validation";
import { GroupsSelectList } from "./../../../../pages/shared/selectLists/GroupsSelectList";
import { ISelectListItem } from "./../../../../modell/common/ISelectListItem";
import HookFormTextArea from "./../../../../library/HookForm/Components/hookFomTextArea";
import { WebAPI } from "src/service/webAPI";
import HookFormCheckbox from "./../../../../library/HookForm/Components/hookFormCheckbox";
import HookFormTextBox from "./../../../../library/HookForm/Components/hookFomTextBox";
import { DegreeSelectList } from "./../../../../pages/shared/selectLists/DegreeSelectList";
import { SexesSelectList } from "./../../../../pages/shared/selectLists/SexesSelectList";
import { CountriesSelectList } from "src/pages/shared/selectLists/CountriesSelectList";

const NewMessagePage: React.FC = () =>
{
    const[groups, setGroups] = useState<ISelectListItem[]>([]);
    const[selectedGroup, setSelectedGroup] = useState<ISelectListItem>();
    const[degrees, setDegrees] = useState<ISelectListItem[]>([]);
    const[sexes, setSexes] = useState<ISelectListItem[]>([]);
    const[countries, setCountries] = useState<ISelectListItem[]>([]);
    const[isVote, setIsVote] = useState<boolean>(false);

    useEffect(() =>
    {
        const fetch = async (): Promise<void> =>
        {
            await WebAPI.Common.groups()
            .then( (data: ISelectListItem[]) => setGroups(data));

            await WebAPI.Common.degrees()
            .then( (data: ISelectListItem[]) => setDegrees(data));

            await WebAPI.Common.sexes()
            .then( (data: ISelectListItem[]) => setSexes(data));

            await WebAPI.Common.countries()
            .then( (data: ISelectListItem[]) => setCountries(data));
        }

        fetch();
    }, []);

    const { control, handleSubmit, errors, register, formState } = useForm<IMessageRequest>
    ({
        mode: "onChange",
        resolver: yupResolver(validationSchema)
    });

    const onSubmit = async (data: IMessageRequest): Promise<void> =>
    {
        data.negativeAnswer = data.negativeAnswer === "" ? undefined : data.negativeAnswer;
        data.positiveAnswer = data.positiveAnswer === "" ? undefined : data.positiveAnswer;

        console.log({...data});
    }

    const QueryParamElement = (): JSX.Element | null =>
    {
        switch (selectedGroup?.id)
        {
            /* country */
            case 2:
                return <CountriesSelectList
                    name="queryParam"
                    label="Cél ország neve"
                    data={countries}
                    placeholder="Kérem válasszon"
                    displayMember={(item: ISelectListItem) => item.name}
                    valueMember={(item: ISelectListItem) => item?.id.toString()}
                    control={control}
                    errors={errors} />

            /* city */
            case 3:
                return <HookFormTextBox
                            name="queryParam"
                            label="Cél város neve"
                            type="text"
                            control={control}
                            errors={errors} />;
            /* degree */
            case 4:
                return <DegreeSelectList
                            name="queryParam"
                            label="Válassza ki az iskola végzettséget"
                            data={degrees}
                            placeholder="Kérem válasszon"
                            displayMember={(item: ISelectListItem) => item.name}
                            valueMember={(item: ISelectListItem) => item?.id.toString()}
                            control={control}
                            errors={errors}
                            reference={register} />;
            /* sex */
            case 5:
                return <SexesSelectList
                            name="queryParam"
                            label="Válassza ki a nemet"
                            data={sexes}
                            placeholder="Kérem válasszon"
                            displayMember={(item: ISelectListItem) => item.name}
                            valueMember={(item: ISelectListItem) => item?.id.toString()}
                            control={control}
                            errors={errors}
                            reference={register} />;
            default: return null;
        }
    }

    return (
    <IonPage>
        <Header text="Új Üzenet Létrehozása" />
        <IonContent fullscreen>
        <form onSubmit={handleSubmit((data: IMessageRequest) => onSubmit(data))}>
            <IonGrid>
                <IonRow>
                    <IonCol size="12" sizeMd={QueryParamElement() === null ? "12" : "6"}>
                        <GroupsSelectList
                            name="groupID"
                            label="Csoport"
                            data={groups}
                            placeholder="Kérem válasszon"
                            displayMember={(item: ISelectListItem) => item.name}
                            valueMember={(item: ISelectListItem) => item?.id.toString()}
                            onChange={ (item: ISelectListItem) => setSelectedGroup(item)}
                            control={control}
                            errors={errors}
                            reference={register} />
                    </IonCol>
                    <IonCol size="12" sizeMd="6">
                        {QueryParamElement()}
                    </IonCol>
                </IonRow>
                <IonRow>
                    <HookFormTextArea
                        name="text"
                        label="Üzenet szövege"
                        autoGrow={true}
                        fullWidth={true}
                        control={control}
                        errors={errors} />
                </IonRow>
                <IonRow>
                    <IonCol size="12" sizeMd="4">
                        <HookFormCheckbox
                            name="isVote"
                            label="Szavazás"
                            onChange={(e: boolean) =>
                                {
                                    setIsVote(e);
                                    console.log(e);
                                }}
                            checked={isVote}
                            control={control}
                            errors={errors} />
                    </IonCol>
                    <IonCol size="12" sizeMd="4">
                        <HookFormTextBox
                            name="positiveAnswer"
                            label="Pozitív válasz szövege"
                            type="text"
                            disabled={!isVote}
                            control={control}
                            errors={errors} />
                    </IonCol>
                    <IonCol size="12" sizeMd="4">
                        <HookFormTextBox
                            name="negativeAnswer"
                            label="Negatív válasz szövege"
                            type="text"
                            disabled={!isVote}
                            control={control}
                            errors={errors} />
                    </IonCol>
                </IonRow>
                <IonRow>

                </IonRow>
                <IonRow>
                    <IonCol>
                        <IonButton expand="block" type="submit" className="ion-margin-top"
                                   disabled={formState.isValid === false}>
                            KÜLDÉS
                        </IonButton>
                    </IonCol>
                </IonRow>
            </IonGrid>
          </form>
        </IonContent>
        <Footer />
    </IonPage>
    );
}

export default NewMessagePage;

标签: typescriptvalidationyupreact-typescript

解决方案


这是我最后所做的:

import * as Yup from "yup";

export const validationSchema = Yup.object().shape
({
      text: Yup
            .string()
            .required("Kötelező mező.")
            .max(2048, "Az üzenet szövege túl hosszú,"),
      groupID: Yup
              .number()
              .min(1, "Kötelező mező.")
              .required("Kötelező mező."),
      queryParam: Yup
                 .mixed()
                 .when("groupID",
                 {
                        is: (groupID: number) => groupID > 1,
                        then: Yup.lazy( (value: any) =>
                        {
                          console.log("value: ", value);
                          if (value === -1 || value === "-1" || value === "" || value === undefined || value === null)
                          {
                                  switch (typeof(value))
                                  {
                                        case "string": return Yup.string()
                                                                 .required("Kötelező mező.");
                                        case "number": return Yup.number()
                                                                 .min(1, "Kötelező mező.");
                                  }
                          }

                          return Yup.mixed()
                                    .notRequired()
                        })
                  }),
      isVoteType: Yup
                 .boolean(),
      positiveAnswer: Yup
                      .string()
                      .when("isVoteType",
                      {
                              is: (isVoteType: boolean) => isVoteType,
                              then: Yup.string()
                                       .required("Kötelező mező.")
                      }),
      negativeAnswer: Yup
                      .string()
                      .when("isVoteType",
                      {
                              is: (isVoteType: boolean) => isVoteType,
                              then: Yup.string()
                                       .required("Kötelező mező.")
                      })
});

推荐阅读