How to Autofocus Form Inputs with React Refs
React can be a very strange language for some developers after working with vanilla Javascript. In vanilla Javascript, if you want to autofocus on an element, select text or playback a video or audio element, you create a variable referencing the target element and then chain on a method, or even use simple prebuilt attributes to set input/element behavior. In React it works a little different. To have this functionality, we use refs.
What is a ref? A ref is an attribute that is added to a target element in a component’s render method that allows us to modify the element in between renders. The normal way to change your UI is through updating state and changing app state or the props passed to the component. Refs offer us a way to change child components or elements without using props.
React originally allowed for two ways to use refs, ref strings and callback functions. The ref strings were found to be too buggy and have since been deprecated. If you are working with StrictMode on, React will throw a warning for you to change to your ref strings to either callback refs, or the more mainstream object refs.
To demonstrate React object refs in action, I have put together a quick demo app (the source code can be found in my repository https://github.com/dpericich/Login-Form). This app is a simple login form with the option to create an account if you do not have one. The goal of this demo is to show autofocus in action. While not every form needs to have autofocus to the first input field on page load, it’s a little comfort that users generally enjoy.
Below is a picture of the initial UI:
Here you can see two input fields as well as a submit button, and a link to open up our popup. From the screenshot you can see that we already have an autofocused input for the “Email / Username” input. When we click on the “Click Here to Create Account” link below the log in form we see that that “Username / Email” input is also autofocused. How did we do this?
To answer that we need to look at our Input component:
This is a modular input component that I use across the whole app. As you can see, nothing is hardcoded which allows us to reuse it with different placeholders, as well as with our without using the autofocus feature.
To setup refs on this component, we need to do three things. First, we make the component a class component. While you can use functional components with a useRef hook to get the same functionality, I chose to use class components because of the ease of creating a ref instance within the class that can be used anywhere in our component and the componentDidMount method that allows us to autofocus when the component renders.
The first thing we want to do to use refs is create an instance of a ref. We do this under point 1 where we call createRef to create our ref instance inputRef. This will be used to store the specific element we want to target and manipulate within our render method.
How do we access this element? Simply put, all we need to do is create a ref attribute within our target element. The value in JS braces is the ref instance we just created. Now, we have access to and can modify our first input element. Our goal with modifying it is to add an autofocus feature whenever the page loads.
Next, we will want to focus on adding this autofocus feature. To do this we will want to perform the action whenever the component loads. This is easy to do by storing our function in the componentDidMount method. Here we will make use of the current property of our ref to modify the element. The current property of our ref allows us to directly modify the instance of the element we targeted. With it, we are able to add the focus method which will cause the page to autofocus on our ref if we pass a focus props with the value of true to this component. Just like that we are in business with a reusable component that can autofocus based off a single Boolean prop!
Autofocus is great, but what are some of the other purposes of refs? Use refs when you are managing focus, text selecting, media playbacks, and animations or integrating other 3rd party libraries. Do not use refs for things that can be done declaratively. Leave a comment of what you’re going to build with refs below!
Sources