React Refs and Custom OTP Modal

Priya Jain
5 min readApr 18, 2020

All of us have been juggling around with DOM since our inception as the developers. As in HTML, we can handle the DOM quite easily and directly, but in React we have JSX.

A quick recap:

The DOM represents a document with a logical tree. Each branch of the tree ends in a node, and each node contains objects. DOM methods allow programmatic access to the tree. With them, you can change the document’s structure, style, or content.

Maximum part of the React, the parent and child component interaction takes place using ‘props’. A child component is modified or re-rendered with new props provided by the parent component. But what if there is a need to interact with the child component by going out of a regular path?

Refs are such a hatch!

As already stated by React docs, ‘refs’ are good to manage elements focus and trigger imperative animations.

So, using such a tool as our power, we’ll create an OTP modal component. You can easily customize this component as per the required number of inputs too.

To get started, let’s set up our basic boiler plate using ‘npx create-react-app custom-modal’. Since the main focus will be on creating custom OTP modal, so I will be using ‘reactstrap’ for basic styling.

Create a new file, ‘OtpDialogBox.js’ (you can name as you like). Import this file into the ‘App.js’.

App.js

Now in ‘OtpDialogBox.js’ , enter the following code:

OtpDialogBox (part 1)

In this class-based component, we are just creating a simple button to trigger ‘openModal’ state to open the modal component.

OtpDialogBox (part 2)

Let’s understand things happened till now bit-wise 🤖.

In part 1, we created a class based component to handle the state of our modal box (we’ll be creating that soon). We then created two functions, openModal() and closeModal() to trigger the state ‘modalOpen’ as either true or false. Notice the parameter received by closeModal() ? It’s being passed from the child component that sets the ‘OTP’ state with the OTP or value received. After receiving the OTP from the child component, we will display it inside the parent component.

P.S. You can utilize the value received as you like. 🙂

In part 2, we added a button to open the modal and rendered our VerifyModal child component conditionally, which is quite easy to relate.

Save the code and we got this:

Let’s move further with the main highlight of this article, ‘Refs’.

Open up a new file named ‘VerifyOtp.js’. Insert the following code into the file.

VerifyModal.js (part 1 )
VerifyModal.js (part 2)

Time for another explanation 🧐.

In the part 1 of this code, we created “refs” for four text input elements inside the constructor(). Then inside the componentDidMount() lifecycle hook, we check if we received props as true and then using the current.focus() property of DOM, the input cursor is made to focus on first text input element as soon as the component mounts. This is an optional step, you can skip if you want.

Now, in the function handleKeyPress(), we store the field that is being passed on each text input box element’s change event. If the input type of next element matches INPUT, then we shift the cursor focus automatically onto the next text input box element using property current.nextSibling.focus(). Then we save the input value received from each input box element to state ‘otp’.

The function submitForm() takes the final OTP from the state and is then passed to the function close() which is received as a prop from it’s parent component.

P.S. Notice the use of e.persist() . If you try to access a React synthetic event in an asynchronous way, it triggers a warning: “Warning: This synthetic event is reused for performance reasons”. To avoid such caveats, we use event.persist() on the event which removes the synthetic event from the pool and allows references to the event to be retained asynchronously.

The function preventSubmit() is used to prevent the user from submitting the OTP using an enter key. “Again! This is optional”.

In the part 2 of this code, we are just rendering a basic form JSX. First, for <form>, we added ‘onKeyPress’ event handler and referenced it to function preventSubmit() to prevent ENTER key to submit form values. Second, for the four input elements, we did the following:

  1. passed the property ‘maxLength = 1’, to allow only single value for each input box.
  2. passed their individual ‘refs’ created in the constructor.
  3. passed the ‘onKeyUp’ event handler and referenced it to handleKeyPress() function created. Also, this function takes the value of each input element as an argument like handleKeyPress(e, this.textInput1), handleKeyPress(e, this.textInput2), and so on..

Finally, we referenced the submit button with submitForm() function.

Compiling everything all together, we get something like this:

Putting it all together in action.

Aaand, it’s done 🥳.

Conclusion

So, you saw how easy and fun it was to create a custom OTP dialog box. You can further customize the same with CSS, number of inputs and data handling on real API as want.

If you liked the article; clap 👏🏻, share 🙂 and subscribe 📑.

--

--