Javascript 使用Formik和material ui stepper上传文件
我试图做一个文件上传,但整个组件每次刷新。我在这里有3个步骤,第一个取名字,第二个取地址,第三个取个人资料。在第三步中,当用户单击按钮从文件系统中选择文件时,整个步进器组件将重新加载 是否有其他方式可以使用文件上载?我不确定我是否能把这些东西和formik值结合起来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); /
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的文档,并尝试使用输入的道具进行调整,当它有错误、被触摸或该输入字段有任何内容时
我确信我的答案现在不起作用,但我认为这是一个很好的方法来遵循我的答案
如果你需要更多的澄清,请告诉我