首页 > 解决方案 > 映射 Formik 文本字段

问题描述

我正在使用材料 ui 文本字段并使用 Formik 验证它们。我不想多次输入所有内容,而是想映射项目,但我无法这样做。

return (
    <div>
      <Formik
        initialValues={{ email: '' }}
        onSubmit={(values, actions) => {
          setTimeout(() => {
            alert(JSON.stringify(values, null, 2));
            actions.setSubmitting(false);
          }, 1000);
        }}
        validationSchema={schema}>
        {props => {
          const {
            values: { email },
            errors,
            touched,
            handleChange,
            isValid,
            setFieldTouched,
          } = props;
          const change = (name: string, e: FormEvent) => {
            e.persist();
            handleChange(e);
            setFieldTouched(name, true, false);
          };
          return (
            <div className="main-content">
              <form
                style={{ width: '100%' }}
                onSubmit={e => {
                  e.preventDefault();
                  submitForm(email);
                }}>
                <div>
                  <TextField
                    variant="outlined"
                    margin="normal"
                    id="email"
                    name="email"
                    helperText={touched.email ? errors.email : ''}
                    error={touched.email && Boolean(errors.email)}
                    label="Email"
                    value={email}
                    onChange={change.bind(null, 'email')}
                  />

{/* {[{ variant:"outlined", margin:"normal", id:"email", name:"email", label: "Email", value: email, onChange:{change.bind(null, 'email')}
          ].map((item, index) => (
            <TextField></TextField>
          ))} */}

                  <br></br>
                  <CustomButton
                    text={'Remove User'}
                  />
                </div>
              </form>
            </div>
          );
        }}
      </Formik>
    </div>
  );

目前在注释掉的部分,我得到了change.bind错误(property) change: (name: string, e: React.FormEvent<Element>) => void ',' expected.ts(1005)

同样,如果我尝试添加helperText:{touched.email ? errors.email : ''}要映射到文本字段的参数列表,我会得到:

(property) touched: FormikTouched<{
    email: string;
}>
',' expected.ts(1005)

touched.email。当我尝试使用时也是如此errors.

(property) touched: FormikTouched<{
    email: string;
}>
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'FormikTouched<{ email: string; }>'.
  No index signature with a parameter of type 'string' was found on type 'FormikTouched<{ email: string; }>'.ts(7053)

标签: javascriptreactjstypescriptmaterial-uiformik

解决方案


谢谢你的沙盒。

根据您的沙箱,我已设法通过该map功能进行字段迭代。

首先分离出独特的现场道具

  1. 属于输入的道具,例如name id label等。
  2. 属于组件的 props 等variant margin handlers

你最终会得到 2 个对象。

(1)一个应该抽象到组件并保存在单独文件中的字段,您以后可以使用另一个组件中的字段。

这里因为你使用 formik 并且你需要有一个 formik 的引用键,所以我formikRef在对象中添加了 。

const fileds = [
  {
    id: "email",
    name: "email",
    formikRef: "email",
    label: "Email"
  },

  {
    id: "name",
    name: "name",
    formikRef: "name",
    label: "Name"
  }
];

(2) 第二个应该存储在组件中的对象,因为它解析了<TextField/>props

我通常将它们包装在 useMemo 钩子中,因此如果未更改依赖对象,则不应重新声明它。这仅用于性能,您也可以使用直接对象

const defaultProps = React.useMemo(() => ({
    textField: {
      variant: 'outlined',
      margin: 'normal',
      onChange: props => {
        formik.handleChange(props);
        formik.handleBlur(props);
      },
      onBlur: formik.handleBlur
    }
  }),
  [formik]
);

//without useMemo

const defaultProps = {
  textField: {
    variant: 'outlined',
    margin: 'normal',
    onChange: props => {
      formik.handleChange(props);
      formik.handleBlur(props);
    },
    onBlur: formik.handleBlur
  }
}

最后一步是在渲染中映射道具

{
  fileds.map(({ formikRef, ...input }) => (
    <TextField
      key={formikRef}
      helperText={getIn(formik.touched, formikRef) ? getIn(formik.errors, formikRef) : ''}
      error={getIn(formik.touched, formikRef) && Boolean(getIn(formik.errors, formikRef))}
      value={getIn(formik.values, formikRef)}
      {...input}
      {...defaultProps.textField}
    />
  ))
}

我还在这里创建了一个工作沙箱

LE:类型检查是一个问题,但可以通过一点搜索找到解决方案......在这里讨论过

为了通过类型检查问题,我进行了更正并添加了getIn辅助函数。Formik


推荐阅读