Overview of React Refs to Clear the Form and Image Uploaders
As you may have noticed, whenever we submit a form on our portfolio, nothing changes on the form so we're able to add the callback so that we could update the sidebar list.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

That is great but if we want to be able to have the traditional kind of form behavior, what a user expects is to be able to submit a form and then all of the elements here should be removed, they should just automatically be cleared off as soon as the form was successfully submitted so that the user could enter in another record. And so that's what we're going to do and we are gonna learn a new concept in this guide. And this is the concept of refs, which is short for references.

Now, this is also going to give us the opportunity to talk about how React works with the DOM. We talked about the DOM quite a bit in several courses. The DOM is the document object model, so that is essentially saying, if you wanna treat even this documentation page here as an HTML document, the entire page is the document.

This heading is probably an h1 tag, that is an object nested inside of the document. If you wanna take it even further, you could probably say that this entire text container right here is probably a div, that is also an object and it has several, quite a few, child components nested inside of it.

That is a traditional document object model. It's a document that is made up of objects, you can select them, you can work with them, and that's how we use tools such as CSS, how we can use pure JavaScript and different tools like that.

But remember, in React, we are actually using what is called a virtual DOM and so what this means is that React doesn't actually allow us directly to interact with the real elements on the page. Instead, it takes up all that JSX code and it converts it into HTML for us, and then it performs the selection.

So when we're saying that we want to say, have a input right here and then we wanna grab the elements in that input, if we were doing that in pure JavaScript, we would have to call the document, so we would say something like document get element by ID, then set the value and take those kinds of tasks into account.

With React, they actually abstract that entire process for us by creating this virtual DOM and that's what we interact with. However, there are a few times where you wanna be able to interact directly with the DOM and so that is what refs do.

A ref is short for reference and it gives you the ability to reference into actually pull away that shadow DOM for an element and to be able to work with it directly. And so, that's what we're going to do and I definitely recommend for you to read this documentation page and hopefully you'll see that we are using this for the right purpose.

It is usually highly discouraged to overuse refs and so you can even see here one of the very first things they say is don't overuse refs,

large

and the reason for that is because if you're overusing these, then you're really not even embracing all of the great tooling that React gives you and it can hurt performance, it can cause a large number of bugs, so you wanna use this very sparingly and we are going to be doing it for exactly what we're talking about. Right here, it says when to use refs, and it says there are a few good use cases.

large

So managing focus, text selection, or media playback; triggering imperative animations; or integrating with third-party DOM libraries.

Now, this is actually exactly what we're doing right here, we're using that dropzone component, it's going to create that uploader on the page, we want to be able to reach in and to grab it, 'cause remember the whole purpose of this is we wanna be able to clear the files as soon as they've been successfully uploaded.

So that is what we're gonna try to build and we're gonna use refs in order to do that. You can see in the documentation, it gives all the instructions but we'll, as always, we'll walk through how to do this in our own application. But part of the reason why I like showing you the documentation is because every single thing that we talked about, everything from day one of this course, all the way through the end and even further beyond that, every one of those items and topics is in the documentation.

So I highly recommend for you to make this your very good friend because when you start building out even more advanced applications, you're going to be referencing this quite a bit. I probably access the React documentation several times a week, if not several times a day just because it has some great examples, has some great explanations, and it really is a great tool.

So I'll put a link to the show notes for this for you but now that I've been talking for way too long, let's actually now start going and let's build it. I'm gonna give a hard refresh here for the PortfolioForm so we can make sure we're working with a clean copy and we can see this testing all three, that last file that we uploaded is still there.

So let's now go and let's start the process of creating refs. I'm gonna start off by giving us the steps needed in order to work with refs. There are three steps and that's nice 'cause it makes it a little bit easier to work with. The very first step is we need to define the ref and you can do this inside of the constructor.

So we're going to create a reference, tie it into the component directly, then from there, we can call that anywhere else. So what we're going to be doing is we're going to define it inside of the constructor, then because we wanna work with it, we're going to be placing it inside of the handleSubmit.

So right now, we're simply calling the handleSuccessfulFormSubmission function prop but we're going to now start clearing the files out and this is gonna be the best spot to do it because we know that if we get this response back and this data back, that the file successfully uploaded and the record was created. And then the third step, the third place that we need to be able to add the ref is we need to tell React what we're trying to reference which that makes sense.

So we're gonna go into each one of the dropzone components and add them in there. So now that we know what we need to do, let's walk through the syntax. So coming up into the constructor, I'm going to give us a couple of lines just so we separate each one of our handlers and now I'm going to add our refs.

So I'll say this. and I'm gonna call this thumbRef just so it's clear on what it is and set it equal to React.createRef just like this and that's a function and so it's create, all lowercase, and then a capital R and what that's going to do is it's going to create a reference object and it's gonna store it inside of thumbRef and then we'll have access to it. We'll have access to put it in the JSX code and then we'll have access to call it from any other function.

So we have our thumbRef, the next one as you may have guessed is going to be our bannerRef and then lastly we'll have a logoRef.

this.thumbRef = React.createRef();
this.bannerRef = React.createRef();
this.logoRef = React.createRef();

Okay, so we have our references and now let's go, and let's add them to JSX first just so we make sure that those are actually there. So go down into your DropzoneComponent here and you can in here just pass this ref indirectly.

So I can say ref equals and then in curly brackets, we bind the ref directly into the component. So for this first one, I'll say this.thumbRef and then let's go and do that for the other two except give them obviously their own unique one so the next one is going to be our bannerRef and then lastly is our logoRef, and hit save, and so now these references are now tied directly into the DropzoneComponent.

This is not something that has anything to do with the component library, this is something in React where React gives us the ability to place a handle directly inside of one of these components on any component on the page. If you wanted to, and this is something please do not ever do this, but if for some weird reason you wanted to, you could put a reference in every single div on the page and then you could access it just like a regular HTML element but that kinda kills the whole point of using React.

I just wanted to say it to tell you that the refs are something that are not specific to dropzone or anything like that, this is something in React, it gives you the ability to interact with the real DOM. And so, now that we have that, let's actually make something happen with it.

So we have that connection and now inside of handleSubmit what we can do is I'm going to just make it a little bit easier. We could call each one of those manually but I think it makes more sense to say this. and then call them inside of an array.

So as you can see, I have the square brackets so I'm going to store each one of these elements in an array because what that is going to allow us to do is loop over it. So instead of just hard coding and manually calling each one of these, I can just list them out.

So I can say this.thumbRef, this.bannerRef, and then this.logoRef, that's all we want inside of that array and then from there, I'm gonna call forEach. So I'm gonna call forEach which is an iterator function in JavaScript so I can say forEach and forEach expects a function so here I'm gonna say as you're iterating over each one of these and I don't want this to seem confusing, all we're literally doing is iterating over each one of these references and then we're gonna be able to call a function on it.

So I'm gonna say that I want access to that reference and now we are gonna get into using some dropzone functions. So when I say ref, I'm referring to this reference which means the first time that this loops through it's gonna be thumbRef, then banner, and then the third time will be logoRef.

Now I can say ref.current which gives us the current state of that element, this is still with React and you can double-check that inside of the React code. So if you want access to the reference, you have to say ref.current and then we're gonna have access to dropzone.

So I'm gonna say dropzone and this is all lowercase, then removeAllFiles and that's a function. Now if you're curious on how in the world I got this information, it was in the dropzone component documentation. So that's all it is, is in the documentation I looked for how can I remove files and it showed me.

So, this is the function that they have built directly into dropzone, so we're accessing the ref which means we're reaching into that object because it's a dropzone object, we can call dropzone and then from there, we have access to the functions built into dropzone, in this case, it is removeAllFiles.

portfolio-form.js

[this.thumbRef, this.bannerRef, this.logoRef].forEach(ref => {
  ref.current.dropzone.removeAllFiles();
});

So I'm gonna hit save and that should take care of everything we need there but we also need to clear off the rest of the form. So if you scroll up to our state definition, what I wanna do is clear off all of our state.

So I'm just gonna copy this and remember, all we need to do in order to get to our base state is go exactly with what we have here and so if I go inside of that handleSubmit, I'm gonna put it right below this callback and I'm not gonna set state manually, that would be highly discouraged, but what I can do is say this.setState and then call this exactly like how we normally would.

So I'm gonna say this.setState and then I'm gonna set each one of these items equal to the empty string except for category because that is one of our defaults and then at the very end here on line make sure after the curly bracket that you put in the paren.

So hit save and so just to do a quick review on what's happening here, when we get the response back, it's going to update the sidebar list 'cause it's calling that prop, then from there, we're setting state. We're going back to our base state where we go and we say okay our name is blank, our description is blank and we go through each one of those items and you may think that oh, well, we're resetting this value in state so why do we even need these references?

The reason is that these, I don't want you to get them confused, our thumb_image, our banner_image, and our logo, those are attributes in our state but what we have here are actually elements inside of the DOM, these are the dropzone components themselves, so what would be very confusing from a bug perspective is say that we didn't implement this removeAllFiles component here and we simply reset the state, you would still have those files lodged inside of the component.

So right here, you would still have the three files and even though our state would be empty and so you'd still have the previews and it would seem to not be working because you weren't actually clearing everything out, so that is an important distinction. Our state is the state of the component but the files that you see in those preview images and those kinds of things, those are built directly into the DOM.

So now that we have all of this, I know that this has been a little bit of a longer video, I'll try to break up the next ones better, but this is a relatively important concept to learn so hopefully you're starting to understand exactly what refs are and how to use them.

So now that you have that, let's come to the browser here, I'm gonna give it one more refresh and let's test this out. So testing all three was the top one so now let's just say testing with refs and then I'm also gonna, this time, I am going to just write in some content inside of here just because I wanna make sure everything gets cleared out and then I will add the three images.

So go to wherever you're keeping your sample images and then just click one for each one of those elements. And then after that, we can hit save and what should happen, if we don't have any bugs, what should happen is this entire form should get submitted and then from there, everything should get cleared out, our form should get cleared out, our images should get cleared out, and we should be back at our base state.

So I'm going to hit Save here and it looks like yes, everything worked.

large

So we have now tested with refs is the newest file, we have each one of the fields was cleared out successfully even eCommerce was reset back to its default value and then the images themselves were removed not just from state but also they were removed from inside of the dropzone component. So great job if you went through that, you just learned a very important key term inside of React which is the ref.

Resources