如何使用formik和MUI将外部API的值设置到输入字段?

问题描述 投票:0回答:1

我正在尝试将 API 中的值输入到使用 formik 的 TextField MUI 组件中。这个想法是,表单是一个组件,我将它用于另一个组件,其中如果一个值来自 API,那么它会作为 prop 传递给表单组件,如果没有传递,则 TextField 组件是渲染以便手动输入值。

这是来自表单组件的代码片段,其中如果我传递了一个属性,则该值设置为

value
并且 TextField 的
onChange
属性可以设置更新使用
 接收到 formik 输入中的值setFieldValue
。我还启用了 formik 上的
enableReinitialize
道具。所有这些都是为了使
isValid
formik 道具识别该值有效并启用提交按钮。

// FormComponent

onst valSchema = Yup.object().shape({
  batchNo: Yup.string()
    .required('Required'),
  item: Yup.string().required('Required'),
  price: Yup.string().required('Required'),
});

const ItemForm = (props) => {
return (
    <Grid container>
      <Grid item xs={12}>
        <Container maxWidth="md">
          <div>
            <Formik
              enableReinitialize
              initialValues={initialValues}
              validationSchema={valSchema}
              onSubmit={(values) => {
                localHandleSubmit(values);
              }}
            >
              {({ dirty, isValid, errors, handleChange, setFieldValue }) => (
                <Form>
                  <Grid container spacing={2}>
                    {props.batchValue ? (
                      <Grid item xs={12}>
                        <TextField name="batchNo" label="Batch No" value={props.batchValue} onChange={(e) => {
                            handleChange(e);
                            setFieldValue('batchNo', props.batchValue);}} />
                      </Grid>
                    ) : (
                      <Grid item xs={12}>
                        <TextField name="batchNo" label="Batch No" />
                      </Grid>
                    )}
                    <Grid item xs={6}>
                      <TextField name="item" label="Item" />
                    </Grid>
                    <Grid item xs={6}>
                      <TextField name="price" label="Price" />
                    </Grid>
                    <Grid item xs={12}>
                      <Button
                        fullWidth
                        variant="contained"
                        disabled={!isValid || !dirty}
                        type="submit"
                      >
                        {' '}
                        ADD
                      </Button>
                    </Grid>
                  </Grid>
                </Form>
              )}
            </Formik>
          </div>
        </Container>
      </Grid>
    </Grid>
  );
};

这就是我将值传递给表单组件的方式。

<DialogContent dividers>
       <FormComponent batchValue={batch} />
</DialogContent>

我遇到的问题是提交按钮未启用,因此我发现 isValid formik 属性为 false 并且需要该值的错误,因此 formik 无法将从 API 传递的值识别为有效。

我想知道如何才能完成这项工作。

javascript reactjs material-ui formik yup
1个回答
0
投票

我知道这个问题很久以前就被问过,但这可能对某人有帮助。技巧是使用

initialValues
对象设置输入值,并使用空字符串回退到普通的可编辑输入。

// Suppose data is the prop returned from an API response
const data = {
  batchNo: "04930",
  item: "Gizmo",
  price: "24.43",
};

<Formik
    enableReinitialize
    initialValues={{
      batchNo: data?.batchNo ?? "",
      item: data?.item ?? "",
      price: data?.price ?? ""
    }}
    validationSchema={valSchema}
    onSubmit={(values) => {
      localHandleSubmit(values);
    }}
  />

现在输入字段的默认值将是来自 API 属性的值。通过利用

??
无效合并运算符,当响应未定义时,我们回退到空的可编辑输入。

要将值输入到输入中,您可以使用 formik

values
对象,而不是直接传递 prop 数据。

{({ dirty, isValid, errors, handleChange, setFieldValue, values }) => (
    <Form>
      <Grid container spacing={2}>
        {values.batchNo ? (
          <Grid item xs={12}>
            <TextField
              name="batchNo"
              label="Batch No"
              value={values.batchNo}
              onChange={(e) => {
                handleChange(e);
                setFieldValue("batchNo", values.batchNo);
              }}
            />
          </Grid>
        ) : (
          <Grid item xs={12}>
            <TextField
              name="batchNo"
              label="Batch No"
              value={values.batchNo}
              onChange={(e) => setFieldValue("batchNo", values.batchNo)}
            />
          </Grid>
        )}
        <Grid item xs={6}>
          <TextField
            name="item"
            label="Item"
            value={values.item}
            onChange={(e) => setFieldValue("item", values.item)}
          />
        </Grid>
        <Grid item xs={6}>
          <TextField
            name="price"
            label="Price"
            value={values.price}
            onChange={(e) => setFieldValue("item", values.price)}
          />
        </Grid>
        <Grid item xs={12}>
          <Button
            fullWidth
            variant="contained"
            disabled={!isValid || !dirty}
            type="submit"
          >
            {" "}
            ADD
          </Button>
        </Grid>
      </Grid>
    </Form>
  )}
© www.soinside.com 2019 - 2024. All rights reserved.