Formik — Handling files and reCaptcha

João Miguel Cunha


formik logo

The purpose of this post is to show some things that some people might struggle with when starting working with Formik.

If you do not yet know about Formik please refer to its Github or these posts:

I’m gonna make these examples simple and understandable for demonstration purposes. I’m also going to leave out some features intentionally so I can throw some challenges at you in the end!

Uploading one file 📎

I’m pretty sure all of us have tried file uploading in forms. In the Formik docs there are no indications or directions for file uploading but it as simple as handling a react-select select box.

All you really need is an entry for the values of Formik (in this case called file) and setup the onChange to use Formiks’ setFieldValue function. Remember we can easily access the uploaded file by using event.currentTarget.files[0]!

It’s easy as:

example function for handling file input

and Formik holds the File object for you. You can do whatever you want with it. Get the name, size and type?

example code for showing file data

So with all this data you can show the image in a little thumbnail below the input like so:

thumbnail example

Checkout the example below to see how you can easily accomplish this. For the thumbnail generation I went really simple. No need for fancy stuff for demonstration purposes.

one file upload with thumbnail example

Uploading multiple files 📎 📎 📎

We’ve seen a single file upload but how about multiple files? And a dropzone? And thumbnails for those files?

I’m gonna use the excellent react-dropzone lib to handle all those dropzone specifics. I’m also going to re-use the Thumbnail component from the previous example to keep things simple.

This will be the end result

3 files uploaded

Formik makes it easy to handle stuff like this. setFieldValue is all you need. Basically you can keep track of an array of files and do everything you need to. Feel free to play around with the example below!

Multiple file upload example

reCaptcha Support 🔐

I wager almost everyone has interacted with some form of Google reCaptcha in the past. Maybe even today you filled a form and ticked that box or played that little game to prove that you’re no bot. Point is, reCaptchas are pretty common when people want to prevent bots from spamming trash at them by continuously submitting their forms.

Let me show you how you can handle a simple recaptcha on your form. For the example I’ll be using the react-recaptcha package to get the api connection.

I’ve used a key that I only use for demonstration purposes. If for any reason it goes down by the time you’re reading this please feel free to input your own and try it out.

Google reCaptcha v2 example

What?! 😅 Were you expecting more work? Remember Formiks goal

was to create a scalable, performant, form helper with a minimal API that does the really really annoying stuff, and leaves the rest up to you.

Well we can simply control it ourselves with the setFieldValue function and handle it in values. Later you would submit it to the server and perform server side validation on the reCaptcha response given!

All together! 💯

Great! You’ve come this far and now you want to know how you’ll apply this in a real scenario and submit the data to the server. Let me help!

Let’s build a form for a user that has a name, email, photo, some attachments and the form must be submitted by validating a reCaptcha.

In the end we’re gonna see how we should send things to the server in order for it to accept the files and the user model.

the final form look

As you can see in the below the form is only submitted when the recaptcha is verified and all our required fields are filled. Feel free to play around with it.

the full example

Formik already handles name and email for free for us. So we just have got to plug the other fields in. It’s as simple as you think

initial values, validation schema and submition code

In order to get those files into the server you must submit them through FormData. I went with the simple way because it works for demonstration purposes and I must keep it as simple and as clear for you.

I’m suggesting async/await but you can use whatever you want!

const res = await fetch(“your post url”, { method: “POST”, body: formData });

And the rest is up to your server stack.

NOTE: The piece of code below may have to differ depending on your backend stack.

for (let i = 0; i <= values.attachments.length; i++) {  formData.append(`attachments[${i}]`, values.attachments[i]);}

Some challenges for you 🎲

At this point you might be wondering why I haven’t done some basic features like clearing the uploaded file, clearing individual uploaded files (from the multiple upload example) or maybe even clear and reset the reCaptcha.

Well, that is YOUR challenge! 😏 😄

In order to brush up those skills free feel to fork up the CodeSandboxes and hack away!

You can try

  • Making a smarter Thumbnail component (react-dropzone actually gives us a preview blob so maybe use it? 😄)
  • Removing a file from the single upload input
  • Removing a(some) file(s) from the multiple upload input
  • Reset the reCaptcha
  • Simplify the FormData append code
  • Make a real submission happen to some API

Have fun coding away! 💻 🎲