React-final-form: Simple file input example

Created on 28 Oct 2019  路  2Comments  路  Source: final-form/react-final-form

There are no examples in the documentation about file inputs, and the issues advise to use react-dropzone, which is overkill if I just want a simple file input.

So I just wanted to share a TypeScript snippet that can be used for file inputs, especially if you want to have a File in your field value (instead of that useless _fakepath_ given by the input value), if you want to create a FormData for example.

import React from "react"
import { Field, FieldProps } from "react-final-form"

const FileField: React.FC<FieldProps<FileList, HTMLInputElement>> = ({ name, ...props }) => (
  <Field name={name}>
    {({ input: { value, onChange, ...input } }) => {
      const handleChange = ({ target }: React.ChangeEvent<HTMLInputElement>) => {
        onChange(target.files) // instead of the default target.value
      }
      return <input {...input} type="file" onChange={handleChange} {...props} />
    }}
  </Field>
)

The trick is to just replace the default change event behavior by giving it the files attribute instead of the value, and leave the input uncontrolled since we extract and ignore the value (this is normal for file inputs).

Then in your onSubmit handler, you will have a FileList as the field value, so you can iterate over it (or just read the first element if it's not a multiple file input) and add each File to your FormData, e.g. if you form has a <FileField name="files" />:

const handleSubmit = async (values: AnyObject) => {
  const payload = new FormData()
  payload.append("file", values.files[0])
  await fetch(uri, {
    method: "POST",
    body: payload, // this sets the `Content-Type` header to `multipart/form-data`
  })
}

Related issues:

24

92

If you like this example, I can make a PR to add it to the docs.
Or it could be the default behavior of the lib for file inputs.

Most helpful comment

Wow thank you! You saved my life.

Looks hacky enough to not be added to the official docs though. I think the lib should have it implemented as a feature instead.

All 2 comments

Wow thank you! You saved my life.

Looks hacky enough to not be added to the official docs though. I think the lib should have it implemented as a feature instead.

Thanks a lot @antoinerousseau. This is exactly what I was looking for. I agree with @mmoo, it would be great having it as a feature in the library.

Was this page helpful?
0 / 5 - 0 ratings