In my previous post titled Formik: How to set initialValues from API I explained briefly what Formik is and why I chose it over React form.
Moreover, in this post, I am going to share a tip for handling files or images upload. Working with file upload in Formik requires a workaround using onChange to set the value to the file in addition to declaring our HTML input tag as the file which we generally do without much effort.
Uploading a Single File
import React, { useCallback } from 'react';
import { Formik, Form, useField, useFormikContext, FormikHelpers } from 'formik';
import { FormLabel, FormGroup, FormControl } from 'react-bootstrap';
const FileUpload = () => {
const [_, meta, helpers] = useField('file');
const { error } = meta;
const { touched } = useFormikContext();
const isInvalid = touched && !!error;
const isValid = touched && !error;
const handleSubmit = useCallback(
(
values: FormValues,
{ setSubmitting }: FormikHelpers<FormValues>
) => {
setSubmitting(false);
// your code to handle uploading files to server via api
}, []);
return (
<Formik
enableReinitialize={true}
initialValues={{ file: null }}
onSubmit={handleSubmit}
>
<Form>
<FormGroup classname="mb-3" controlid="file">
<FormLabel>Select a File:</FormLabel>
<FormControl
name="file"
type="file"
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
helpers.setValue(event.currentTarget.files[0]);
}}
{...{ isInvalid, isValid }}
/>
<FormControl.Feedback type="invalid">{error}</FormControl.FeedBack>
</FormControl>
</FormGroup>
</Form>
</Formik>
)
};
export { FileUpload };
Like I already mentioned above, the important piece of code that we should concentrate is onChange
method inside FormControl where we use Formik helpers method to set a file value. This is because Formik doesn't support file upload by default.
Let's see an extract onChange
method:
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
helpers.setValue(event.currentTarget.files[0]);
}}
So, now you can select a file from a Formik. What if you want to upload multiple files? That can be done as similarly as selecting a file. You will just need to pass file values to the helpers method and the rest of the component is the same. That's pretty much it!
Uploading Multiple Files
Let's see a code snippet of onChange
method for uploading multiple files. Here, we pass all files to the helper method instead of a single file (event.currentTarget.files[0]
).
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
helpers.setValue(event.currentTarget.files);
}}
Conclusion
Handling files upload in Formik requires a bit more work than a common input tag with type as the file. But, that is not discouraging me not using Formik in my current project as the tweak is pretty simple and has huge benefits from Formik.