微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

React TypeScript、HooksForm、是的和 MaterialUI 自动完成

如何解决React TypeScript、HooksForm、是的和 MaterialUI 自动完成

我在 React Hook From 中使用 Yup 进行 MUI 自动完成验证时遇到问题。当我 concole.log 我的对象 (GrandLodge) 时,countryIDunionID 的道具总是 "0"

这是我的组件。

  • 首先是我控制的自动完成:
import { TextField,Typography } from "@material-ui/core";
import { Autocomplete } from "@material-ui/lab";
import React,{ ChangeEvent } from "react";
import { Control,Controller,DeepMap,FieldError } from "react-hook-form";
import { Country,Union } from "./../../../service/client";
import { IBaseProps } from "./../Interfaces/BaseProps";
  Country,GrandLodge,Lodge,Union,} from "./../../../service/client";
import { IBaseProps } from "./../Interfaces/BaseProps";

interface IHookFormSelectlistProps<T> extends IBaseProps {
  name: string;
  control: Control;
  errors?: DeepMap<Record<string,any>,FieldError>;
  disabled?: boolean;
  data: Array<T>;
  displayMember: (item: T) => string;
  valueMember: (item: T) => string;
  style?: React.Cssproperties;
  selectedValue?: any;
  onChange?: (item: T) => void;
  label?: string;
  className?: string;
  value: T | null;
}

interface IHookFormSelectlistState {
  setopen: boolean;
}

type CustomSelect<T> = new (
  props: IHookFormSelectlistProps<T>
) => HookFormSelectList<T>;

class HookFormSelectList<T> extends React.Component<
  IHookFormSelectlistProps<T>,IHookFormSelectlistState
> {
  constructor(props: IHookFormSelectlistProps<T>) {
    super(props);

    this.state = {
      setopen: false,};
  }

  private onInputChange = (
    e: ChangeEvent<{}>,value: string | T | null
  ): void => {
    if (this.props.onChange) {
      const item: T = this.props.data.toEnum().First((x: T) => x === value);
      this.props.onChange(item);
    }
  };

  render() {
    const body = () => (
      <React.Fragment>
        <Controller
          render={({ value,onBlur,onChange }) => (
            <div className={this.props.className}>
              <Autocomplete
                freeSolo
                fullWidth
                openOnFocus={true}
                onChange={(e: ChangeEvent<{}>,v: string | T | null) => {
                  onChange(e);
                  this.onInputChange(e,v);
                }}
                onopen={() => this.setState({ ...this.state,setopen: true })}
                onClose={() => this.setState({ ...this.state,setopen: false })}
                getoptionSelected={(option,selected) => option === selected}
                getoptionLabel={this.props.displayMember}
                options={this.props.data}
                loading={false}
                renderInput={(params) => (
                  <TextField
                    {...params}
                    variant="outlined"
                    placeholder={this.props.label}
                  />
                )}
              />
            </div>
          )}
          defaultValue={this.props.value}
          name={this.props.name}
          control={this.props.control}
          onChangeName="onChange"
        />
        {this.props.errors && this.props.errors[this.props.name] && (
          <Typography variant="caption" color="error">
            <small>
              <span role="alert" id={`${this.props.name}Error`}>
                {this.props.errors[this.props.name].message}
              </span>
            </small>
          </Typography>
        )}
      </React.Fragment>
    );

    return body();
  }
}

export const CountriesSelect: CustomSelect<Country> = HookFormSelectList;
export const UnionSelect: CustomSelect<Union> = HookFormSelectList;
  • 我是的验证架构:
import * as Yup from "yup";

export const validationSchema = Yup.object().shape({
  name: Yup.string()
    .required("This field is required.")
    .min(2,"Lodge name has to be at last 2 charachters long.")
    .max(255,"Name can't be longer then 255 charachters."),countryId: Yup.string()
    .required("This field is required.")
    .min(0,"Country has to be selected."),email: Yup.string()
    .required("This field is required.")
    .email("Not a valid e-mail adress."),unionId: Yup.string()
    .required("This field is required.")
    .min(0,"Union has to be selected."),pypalAccount: Yup.string()
    .required("This field is required.")
    .min(2,"Pypal account has to be at last 2 charachters long.")
    .max(255,"Pypal account can't be longer then 255 charachters."),cryptoWallet: Yup.string()
    .required("This field is required.")
    .min(2,"Crypto wallet has to be at last 2 charachters long.")
    .max(255,"Crypto wallet can't be longer then 255 charachters."),});
  • 我的 GrandLodge 对象:
export interface GrandLodge {
  time: Date;
  timeStamp: Date;
  readonly grandLodgeId: number;
  unionId: number;
  countryId: number;
  name: string | undefined;
  email: string | undefined;
  pypalAccount: string | undefined;
  cryptoWallet: string | undefined;
}
  • 还有我的组件:
import { yupResolver } from "@hookform/resolvers/yup";
import {
  Button,Container,CssBaseline,Grid,Typography,} from "@material-ui/core";
import React,{ useEffect,useState } from "react";
import { useForm } from "react-hook-form";
import HookFormTextBox from "./../../../library/HookForm/Components/hookFomTextBox";
import { useStyles } from "./../../style.main";
import { validationSchema } from "./validationSchema";
import { Country,Union } from "./../../../service/client";
import {
  CountriesSelect,UnionSelect,} from "./../../../library/HookForm/Components/hookFormSelectlist";
import { withConnected } from "../../../state/withConnected";
import { WebAPI } from "./../../../service/webAPI";

interface IProps {
  countries: Country[];
}

const GrandLodgePageBase = (props: IProps): JSX.Element => {
  const [serverError,setServerError] = useState<string>("");
  const [unions,setUnions] = useState<Union[]>([]);

  useEffect(() => {
    const fetchData = async (): Promise<void> => {
      setUnions(await WebAPI.Union.getPage(0,1000));
    };

    fetchData();
  },[]);

  const classes = useStyles();

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

  const onSubmit = async (data: GrandLodge): Promise<void> => {
    if (!formState.isValid) {
      return;
    }

    console.log(data);
  };

  return (
    <Container component="main" maxWidth="xl">
      <CssBaseline />
      <Typography className={classes.title} variant="overline">
        Add new grand lodge
      </Typography>
      <form
        className={classes.form}
        onSubmit={handleSubmit((data: GrandLodge) => onSubmit(data))}
      >
        <Grid container className={classes.root} spacing={2}>
          <Grid item xs={12} sm={12} md={12} lg={6}>
            <HookFormTextBox
              name="name"
              type="text"
              label="Lodge Name"
              control={control}
              errors={errors}
              className={classes.formElement}
            />
          </Grid>
          <Grid item xs={12} sm={12} md={12} lg={6}>
            <HookFormTextBox
              name="email"
              type="email"
              label="E-mail"
              control={control}
              errors={errors}
              className={classes.formElement}
            />
          </Grid>
        </Grid>

        <Grid container className={classes.root} spacing={2}>
          <Grid item xs={12} sm={12} md={12} lg={6}>
            <CountriesSelect
              name="countryId"
              label="Country"
              displayMember={(x) => x.name!}
              valueMember={(x) => x.countryId.toString()}
              value={null}
              data={props.countries}
              control={control}
              errors={errors}
              className={classes.formElement}
            />
          </Grid>
          <Grid item xs={12} sm={12} md={12} lg={6}>
            <UnionSelect
              name="unionId"
              label="Union"
              displayMember={(x) => x.name!}
              valueMember={(x) => x.unionId.toString()}
              data={unions}
              value={null}
              control={control}
              errors={errors}
              className={classes.formElement}
            />
          </Grid>
        </Grid>

        <Grid container className={classes.root} spacing={2}>
          <Grid item xs={12} sm={12} md={12} lg={6}>
            <HookFormTextBox
              name="cryptoWallet"
              type="text"
              label="Crypto Wallet"
              control={control}
              errors={errors}
              className={classes.formElement}
            />
          </Grid>
          <Grid item xs={12} sm={12} md={12} lg={6}>
            <HookFormTextBox
              name="pypalAccount"
              type="text"
              label="Pypal Account"
              control={control}
              errors={errors}
              className={classes.formElement}
            />
          </Grid>
        </Grid>

        <Grid item xs={12} sm={12} md={12} lg={12} justify="center" container>
          <Button
            type="submit"
            variant="contained"
            color="primary"
            className={classes.submit}
            disabled={!formState.isValid}
          >
            SAVE
          </Button>
        </Grid>
        <Grid item md>
          <Typography variant="subtitle2" color="error" align="center">
            {serverError}
          </Typography>
        </Grid>
      </form>
    </Container>
  );
};

const GrandLodgePage = withConnected(GrandLodgePageBase,(s) => ({
  countries: s.state.countries,}));

export default GrandLodgePage;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?