Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/455.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用Formik和material ui stepper上传文件_Javascript_Reactjs_File Upload_Material Ui_Formik - Fatal编程技术网

Javascript 使用Formik和material ui stepper上传文件

Javascript 使用Formik和material ui stepper上传文件,javascript,reactjs,file-upload,material-ui,formik,Javascript,Reactjs,File Upload,Material Ui,Formik,我试图做一个文件上传,但整个组件每次刷新。我在这里有3个步骤,第一个取名字,第二个取地址,第三个取个人资料。在第三步中,当用户单击按钮从文件系统中选择文件时,整个步进器组件将重新加载 是否有其他方式可以使用文件上载?我不确定我是否能把这些东西和formik值结合起来 export default function Test() { const showFileToUpload = (e) => { console.log("files", e); /

我试图做一个文件上传,但整个组件每次刷新。我在这里有3个步骤,第一个取名字,第二个取地址,第三个取个人资料。在第三步中,当用户单击按钮从文件系统中选择文件时,整个步进器组件将重新加载

是否有其他方式可以使用文件上载?我不确定我是否能把这些东西和formik值结合起来

export default function Test() {
  const showFileToUpload = (e) => {
    console.log("files", e);
    //then perform some requests to save these images
  };

  return (
    <FormikStepper
      initialValues={{
        firstName: "",
        address: "",
        file: ""
      }}
      onSubmit={async (values) => {
        console.log("values", values);
      }}
    >
      <FormikStep label="Basic Details">
        <FormControl>
          <Field
            type="text"
            name="firstName"
            label="Name"
            component={TextField}
            autoComplete="off"
          />
        </FormControl>
      </FormikStep>
      <FormikStep label="Other details">
        <FormControl>
          <Field
            type="text"
            name="address"
            label="address"
            component={TextField}
            autoComplete="off"
          />
        </FormControl>
      </FormikStep>
      <FormikStep
        label="Upload Files"
        showFileToUpload={(w) => {
          console.log(w);
        }}
      >
        <div className="form-group">
          <label>Upload your images</label>
          <input
            id="file"
            name="file"
            type="file"
            multiple={true}
            onChange={(e) => {
              showFileToUpload(e.currentTarget.files);
            }}
          />
          {/* <Thumb file={values.file} /> */}
        </div>
      </FormikStep>
    </FormikStepper>
  );
}

export function FormikStep({ children, ...props }) {
  console.log("valuessss", props);

  return (
    <Card style={{ width: "100%", marginBottom: "20px", padding: "10px" }}>
      <CardContent
        className="cardContentCustom"
        style={{
          width: "100%",
          marginBottom: "20px",
          display: "flex",
          flexWrap: "wrap"
        }}
      >
        {children}
      </CardContent>
    </Card>
  );
}

export function FormikStepper({ children, ...props }) {
  const childrenArray = React.Children.toArray(children);
  const [step, setStep] = useState(0);
  const currentChild = childrenArray[step];
  const [completed, setCompleted] = useState(false);
  console.log("values", props, childrenArray);

  function isLastStep() {
    return step === childrenArray.length - 1;
  }

  return (
    <Formik
      {...props}
      validationSchema={currentChild.props.validationSchema}
      onSubmit={async (values, helpers) => {
        console.log("--------", props);
        if (isLastStep()) {
          await props.onSubmit(values, helpers);
          setCompleted(true);
        } else {
          setStep((s) => s + 1);
        }
      }}
    >
      {({ isSubmitting }) => (
        <Form autoComplete="off">
          <Card
            style={{
              width: "100%",
              marginBottom: "20px",
              height: "fit-content"
            }}
          >
            <CardContent style={{ width: "100%" }}>
              <Stepper alternativeLabel activeStep={step}>
                {childrenArray.map((child, index) => (
                  <Step
                    key={child.props.label}
                    completed={step > index || completed}
                  >
                    <StepLabel>{child.props.label}</StepLabel>
                  </Step>
                ))}
              </Stepper>
            </CardContent>
          </Card>

          {currentChild}

          <Grid container spacing={2}>
            {step > 0 ? (
              <Grid item>
                <Button
                  disabled={isSubmitting}
                  variant="contained"
                  color="primary"
                  onClick={() => setStep((s) => s - 1)}
                >
                  Back
                </Button>
              </Grid>
            ) : null}
            <Grid item>
              <Button
                startIcon={
                  isSubmitting ? <CircularProgress size="1rem" /> : null
                }
                disabled={isSubmitting}
                variant="contained"
                color="primary"
                type="submit"
              >
                {isSubmitting ? "Submitting" : isLastStep() ? "Submit" : "Next"}
              </Button>
            </Grid>
          </Grid>
        </Form>
      )}
    </Formik>
  );
}

下面是codesandbox的链接:

我记得几个月前我用Antdesign做过ot。antdesign组件不适合像这样在formik表单中集成。所以我不得不用formik的FormItem包起来让它工作

基本上,您可以使用FormItem创建一个与Formik兼容的字段。然后在其中传递材质ui组件,并向其传播formik的道具

您可能需要重构onInputChange/onChange方法以适应materialUi组件方法或文件转换器所需的任何方法

import React from "react";
import { Input } from "@material-ui/core";
import InputFile from "./InputFile";

const CreateFields = (CustomComponent) => ({
  field,

  hasFeedback,
  label,
  selectOptions,
  submitCount,
  type,
  ...props
}) => {
  //this will now trigger an error
  const touched = form.touched[field.name];
 //this will now trigger an error
  const submitted = submitCount > 0;
 //this will now trigger an error
  const hasError = form.errors[field.name];
  const submittedError = hasError && submitted;
  const touchedError = hasError && touched;
  const onInputChange = ({ target: { value } }) =>
    form.setFieldValue(field.name, value);
  const onChange = (value) => form.setFieldValue(field.name, value);
  const onBlur = () => form.setFieldTouched(field.name, true);
  return (
    <div className="field-container">
      <Input
        label={label}
        hasFeedback={
          (hasFeedback && submitted) || (hasFeedback && touched) ? true : false
        }
        help={submittedError || touchedError ? hasError : false}
        validateStatus={submittedError || touchedError ? "error" : "success"}
      >
        <CustomComponent
          {...field}
          {...props}
          onBlur={onBlur}
          onChange={type ? onInputChange : onChange}
        ></CustomComponent>
      </Input>
    </div>
  );
};

export const MyCustomFormikAndMaterialUiField = CreateFields(InputFile);
如果你看到//这不会触发错误,那是因为我不知道材质ui如何处理输入的道具

您需要检查材质ui的文档,并尝试使用输入的道具进行调整,当它有错误、被触摸或该输入字段有任何内容时

我确信我的答案现在不起作用,但我认为这是一个很好的方法来遵循我的答案

如果你需要更多的澄清,请告诉我