Exercise: Can't Be Empty

Exercise 11 Easy

Prerequisites for the exercise

  1. React Forms — Basics

Objective

Create a form with an input field that can't be submitted empty.

Description

Consider the following HTML form containing a text input and a button to submit the form:

An illustration of the form
An illustration of the form

If the form is submitted with the input field empty, the form doesn't actually get submitted, i.e. its default action is prevented.

In this case (that is, when the input field is empty and the form is submitted), an error message, colored red, is shown right next to the input field as shown below:

Form submitted with empty input field
Form submitted with empty input field

However, when the input is not empty and the form is submitted in this state, an alert message is shown as follows:

Alert message shown after form submitted with input value
Alert message shown after form submitted with input value

Keep in mind that in neither case is the form actually submitted (that is, no HTTP request is made to send the form). The <form> element is purely meant to represent a form in the document's content; it doesn't actually behave like a traditional form in its submission.

In this exercise, you have to create a program containing the form described above.

The form should be directly a part of an App component in your program.

Moreover, keep in mind that you should NOT use state to obtain the value of the <input> element.

While it is obviously possible to use state, you should try solving the exercise without it for the <input> element and test your knowledge of using other ways to interact with an <input> element in a form in React.

View Solution

New file

Inside the directory you created for this course on React, create a new folder called Exercise-11-Can't-Be-Empty and put the .js solution files for this exercise within it.

Solution

Let's start by setting up the general structure of the App component, containing the form:

function App() {
   return (
      <form>
         <input type="text" />
         <br/>
         <button>Submit</button>
      </form>
   );
}

Now, let's set up the onSubmit event handler prop on <form> and prevent the default action in there to begin with:

function App() {
   function handleSubmit(e) {
      e.preventDefault();
   }
   return (
      <form onSubmit={handleSubmit}>
         <input type="text" />
         <br/>
         <button>Submit</button>
      </form>
   );
}

As stated in the description above, there is no need to use state. Likewise, in order to retrieve the value of the input, we can use a ref on the <input> element, named inputRef.

This is done as follows:

import { useRef } from 'react';

function App() {
const inputRef = useRef(); function handleSubmit(e) { e.preventDefault(); } return ( <form onSubmit={handleSubmit}> <input type="text" ref={inputRef} /> <br/> <button>Submit</button> </form> ); }

If the retrieved value is an empty string, i.e. there is nothing entered into the input, we should display an error message right next to the <input> element by rendering a <span> containing the message.

This mandates us to use state to trigger a re-render of the App component with a state value called error set to a string describing an error message — this state value is initialized to null because initially no error ought to be shown.

Here's the complete code obtained thus far:

import { useState, useRef } from 'react';

function App() {
   const inputRef = useRef();
const [error, setError] = useState(null); function handleSubmit(e) { e.preventDefault();
if (inputRef.current.value === '') {
setError("Can't be empty!");
} } return ( <form onSubmit={handleSubmit}> <input type="text" ref={inputRef} />
{error && <span style={{ color: 'red' }}>{error}</span>} <br/> <button>Submit</button> </form> ); }

On the other side of the mirror, if the input value is not an empty string, we should alert the message 'Submitted'. This can either be done by using an else statement, or by returning control in the if statement and then having a normal statement following the if conditional.

We'll go with the latter, as shown below:

function App() {
   const inputRef = useRef();
   const [error, setError] = useState(null);

   function handleSubmit(e) {
      e.preventDefault();
      if (inputRef.current.value === '') {
         setError("Can't be empty!");
return; }
setError(null);
alert('Submitted'); } return ( <form onSubmit={handleSubmit}> <input type="text" ref={inputRef} /> {error && <span style={{ color: 'red' }}>{error}</span>} <br/> <button>Submit</button> </form> ); }

Let's now test this implementation of App:

Live Example

It works absolutely perfectly!

And this completes this exercise.