带有 Ionic-React 选择的 React-Hooks-Form 不返回所选值

Posted

技术标签:

【中文标题】带有 Ionic-React 选择的 React-Hooks-Form 不返回所选值【英文标题】:React-Hooks-Form with Ionic-React select not returning selected value 【发布时间】:2021-04-28 13:14:43 【问题描述】:

我正在尝试通过 React-Hooks-Form 库构建我的组件。我在我的项目中使用 Ionic 5 和 React。我设法解决了我的所有组件,除了选择组件。它被渲染,它有项目,我可以选择项目,但是在提交时我没有取回对象中的选定值。 这是我尝试过的:

export interface CompetitionReuqest 
    address: string;
    courseId: number;
    date: Date;
    departmentId: number;
    description: string;
    documentLink: string;
    imageLink: string;
    place: string;
    title: string;
    typeId: number;
    isPayable: boolean;
    isInternational: boolean;
    isGroup: boolean;


export interface IHookFormSelectlistProps<T> extends IBaseProps

    label: string;
    value?: string;
    data: T[];
    placeholder?: string;
    displayMember: (item: T) => string;
    valueMember: (item: T) => string;
    onChange?: (item: T) => void;
    reference<TFieldElement extends FieldElement<T>>(rules?: RegisterOptions): (ref: (TFieldElement & Ref) | null) => void;


function HookFormSelectList<T>(props: IHookFormSelectlistProps<T>): JSX.Element

    const [selectedValue, setSelectedValue] = useState<string>();

    useEffect(() =>
    
      if (props.value)
      
        setSelectedValue(props.value);
      
    , []);

    return (
        <React.Fragment>
            <IonItem>
                
                props.label &&
                <IonLabel position="floating" class="label">props.label</IonLabel>
                
                <Controller render= ( value, onBlur, onChange ) =>
                            (
                              <IonSelect
                                aria-invalid=props.errors && props.errors[props.name] ? "true" : "false"
                                aria-describedby=`$props.nameError`
                                onBlur=onBlur
                                onIonChange=(e) =>
                                
                                  const item: T = props.data.toEnum()
                                                  .FirstOrDefault((x: T) => props.valueMember(x) === e.detail.value);
  
                                  if (props.onChange && item)
                                  
                                    setSelectedValue(props.valueMember(item));
                                    props.onChange(item);
                                  

                                  onChange();
                                
                                value=selectedValue
                                defaultValue=selectedValue
                                disabled=props.disabled ? props.disabled : false
                                placeholder=props.placeholder ? props.placeholder : "Válasszon ...">
                                props.data.map((item) =>
                                (
                                  <IonSelectOption
                                    key=props.valueMember(item)
                                    value=props.valueMember(item)
                                    class="ion-select">
                                    props.displayMember(item)
                                  </IonSelectOption>
                                ))
                                </IonSelect>
                            )
                            defaultValue=setSelectedValue
                            name=props.name
                            control=props.control
                            onChangeName="onIonChange" />
            </IonItem>
            
                props.errors && props.errors[props.name] &&
                (
                    <IonText color="danger" className="ion-padding-start">
                        <small>
                            <span role="alert" id=`$props.nameError`>
                                props.errors[props.name].message
                            </span>
                        </small>
                    </IonText>
                )
            
        </React.Fragment>
    );


export default HookFormSelectList;

export function TypeSelectList(selectProps: IHookFormSelectlistProps<TypeEntity>): JSX.Element

    return HookFormSelectList<TypeEntity>(selectProps);


export function DepartmentSelectList(selectProps: IHookFormSelectlistProps<DepartmentEntity>): JSX.Element

    return HookFormSelectList<DepartmentEntity>(selectProps);


export function CourseSelectList(selectProps: IHookFormSelectlistProps<CourseEntity>): JSX.Element

    return HookFormSelectList<CourseEntity>(selectProps);

以及如何使用它。我需要一个 onChange 事件,也可以在外面使用! 我的 react-hook-form 表单实现【不是所有代码,这只是相关部分】:

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

    const onSubmit = async (data: CompetitionReuqest): Promise<void> =>
        
            console.log("data:");
            console.log(...data);
        

return (
    <React.Fragment>
        <InformationToast enabled=showToast
                          message="A versenyfelhívás feltöltése sikeres volt."
                          onClick=() => onToasInformationClick()/>
        <form onSubmit=handleSubmit((data: CompetitionReuqest) => onSubmit(data))>
            <IonGrid>
                <IonRow>
                    <IonCol sizeXl="4" sizeLg="12" sizeMd="12" sizeSm="12" sizeXs="12">
                        <DepartmentSelectList
                            name="departmentId"
                            label="Iskola típus"
                            value=department?.name
                            data=departments
                            placeholder="Kérem válasszon"
                            displayMember=(item: DepartmentEntity) => item.name
                            valueMember=(item: DepartmentEntity) => itemname
                            onChange=(item: DepartmentEntity) => onDepartmentChanged(item)
                            control=control
                            errors=errors
                            reference=register />
                    </IonCol>
                    <IonCol sizeXl="4" sizeLg="12" sizeMd="12" sizeSm="12" sizeXs="12">
                        <CourseSelectList
                            name="courseId"
                            label="Tantárgy"
                            value=course?.name
                            data=courses
                            placeholder="Kérem válasszon"
                            displayMember=(item: CourseEntity) => item.name
                            valueMember=(item: CourseEntity) => item.name
                            onChange=(item: CourseEntity) => onCourseChanged(item)
                            control=control
                            errors=errors
                            disabled=disableCourses
                            reference=register  />
                    </IonCol>
                    <IonCol sizeXl="4" sizeLg="12" sizeMd="12" sizeSm="12" sizeXs="12">
                        <TypeSelectList
                            name="typeId"
                            label="Verseny típus"
                            value=type?.name
                            data=types
                            placeholder="Kérem válasszon"
                            displayMember=(item: TypeEntity) => item.name
                            valueMember=(item: TypeEntity) => item.name
                            onChange=(item: TypeEntity) => onTypeChanged(item)
                            control=control
                            errors=errors
                            reference=register />
                    </IonCol>
                </IonRow>
                <IonRow>
                    <IonCol>
                    <IonButton expand="block" type="submit" className="ion-margin-top"
                               disabled=formState.isValid === false>
                            MENTÉS
                        </IonButton>
                    </IonCol>
                </IonRow>
            </IonGrid>
        </form>
    </React.Fragment>
    );

【问题讨论】:

嗨!你从哪里导入 TFieldElement 。我试图将寄存器作为道具传递给输入组件,所以我需要将其作为道具 ref: (ref: (TFieldElement & Ref) | null) => void;但是我无法弄清楚 TFieldElement。它既不是 React 也不是 react-hooks-form 【参考方案1】:

我认为你缺少的是:

onIonChange = 
   (e) => 
     /********************* other code */
     value = props.valueMember(item);
     console.log("value from render before internal onChange:" + value);

     onChange(e); //<============= pass the e input to the onChange callback
   ,
 ;

【讨论】:

Taghi Khavari,非常感谢。我看了 2 天的代码,现在注意到了。 @Wasyster 很高兴我能帮上忙。干杯

以上是关于带有 Ionic-React 选择的 React-Hooks-Form 不返回所选值的主要内容,如果未能解决你的问题,请参考以下文章

使用react Context(Ionic-React)时未定义history.push()[重复]

Axios + Ionic React + Sails:_csrf token 403 Forbidden

如何正确使用带有 react-redux 的 useSelector 钩子的 curried 选择器函数?

带有 React JS/Polymer 的主题 css 选择器

在带有 react-router 的 React 中,当我从一个复杂的视图中导航出来,然后直接返回时,如何保留一个人的所有视图选择?

React Native - 带有条件的 OneSignal 推送通知概念设置