Home > Back-end >  How to know if form input is empty (React Hooks)
How to know if form input is empty (React Hooks)

Time:02-21

I have a form where I want to know if the input values ​​are empty when onSubmit, they are not sent. I have tried to do it through the if of handleInputChange but this isn't working:

const handleInputChange = (e: React.FormEvent<HTMLInputElement>) => {
        if ((e.target as HTMLInputElement).value) {
            setNewPost({
                ...newPost,
                [(e.target as HTMLInputElement).name]: (e.target as HTMLInputElement).value
            })
        }
        e.preventDefault();
    };

All the code:

const New: React.FC = () => {
    // const [newPost, setNewPost] = useState("");
    const [newPost, setNewPost] = useState({
        title: '',
        author: '',
        content: ''
    })


    const handleInputChange = (e: React.FormEvent<HTMLInputElement>) => {
        if ((e.target as HTMLInputElement).value) {
            setNewPost({
                ...newPost,
                [(e.target as HTMLInputElement).name]: (e.target as HTMLInputElement).value
            })
        }
        e.preventDefault();
    };

const createPost = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault(); //Detiene el formulario para que no actualize la página
    setPost(newPost)
}



return (
    <div className="containerHomepage">
        <form className="formulari" onSubmit={createPost}>
            <div className="containerBreadCrumb">
                <ul className="breadCrumb">
                    <li>Posts</li>
                </ul>
            </div>

            <div className="containerTitleButton">
                <input
                    className=""
                    type="text"
                    placeholder='Post title'
                    name="title"
                    onChange={handleInputChange}
                ></input>
                <button
                    className="button"
                    type="submit"
                >Save</button>
            </div>

            <div className="containerEdit">
                <input
                    className=""
                    type="text"
                    placeholder='Author'
                    name="author"
                    onChange={handleInputChange}
                ></input>
                <input
                    className=""
                    type="text"
                    placeholder='Content'
                    name="content"
                    onChange={handleInputChange}
                ></input>
            </div>

        </form>
    </div>
);
};


// ========================================

export default New;

CodePudding user response:

Your current handleInputChange makes it so that the user cannot change any input to an empty string. There's a major usability flaw here. Once the user types the first character, they cannot delete it! You should allow the inputs to be empty, but disallow submitting the form unless all fields are filled out.

You can use e.currentTarget instead of e.target to avoid a lot of type assertions. There is more information in this question, but what's important here is that e.currentTarget will always be the HTMLInputElement.

const handleInputChange = (e: React.FormEvent<HTMLInputElement>) => {
  setNewPost({
    ...newPost,
    [e.currentTarget.name]: e.currentTarget.value
  });
};

@rax's answer is on the right track, but I'm going to go further down that path.


An any point in time, you can know whether the form is valid or not by looking at the current state of newPost. There are lots of ways to write this, which all do the same thing:

const isValid = Boolean(newPost.title && newPost.author && newPost.content);

Using type coercion. All strings are truthy except for the empty string.

const isValid = newPost.title !== '' && newPost.author !== '' && newPost.content !== '';

From @Vladimir Trotsenko's answer.

const isValid = Object.values(newPost).every(value => value.length > 0)

Looping over all values of newPost so you don't need to change anything if you add an extra field.


You can use this isValid variable to conditionally disable the "Save" button.

<button type="submit" disabled={!isValid}>Save</button>

You can also use isValid to show messages or other visible feedback to the user. For example, you can show a message when hovering over the disabled button which tells them why it has been disabled.

<button
  type="submit"
  disabled={!isValid}
  title={isValid ? "Create your post" : "All fields must be filled out."}
>
  Save
</button>

I'm checking if (isValid) in the createPost function to be on the safe side, but I believe that this is not actually necessary as the form won't be submitted (even when hitting Enter) if the submit button is disabled.

const createPost = (e: React.FormEvent<HTMLFormElement>) => {
  e.preventDefault(); // stop the form from reloading the page.
  if (isValid) {
    // put your actual code here instead.
    alert("submit success");
  }
};

Complete code:

import React, { useState } from "react";

const New: React.FC = () => {
  const initialState = {
    title: "",
    author: "",
    content: ""
  };
  const [newPost, setNewPost] = useState(initialState);

  const isValid = Boolean(newPost.title && newPost.author && newPost.content);

  const handleInputChange = (e: React.FormEvent<HTMLInputElement>) => {
    setNewPost({
      ...newPost,
      [e.currentTarget.name]: e.currentTarget.value
    });
  };

  const createPost = (e: React.FormEvent<HTMLFormElement>) => {
    e.preventDefault(); //stop the form from reloading the page
    if (isValid) {
      alert("submit success");
    }
  };

  return (
    <div className="containerHomepage">
      <form className="formulari" onSubmit={createPost}>
        <div className="containerBreadCrumb">
          <ul className="breadCrumb">
            <li>Posts</li>
          </ul>
        </div>

        <div className="containerTitleButton">
          <input
            className=""
            type="text"
            placeholder="Post title"
            name="title"
            onChange={handleInputChange}
            value={newPost.title}
          />

          <button
            className="button"
            type="submit"
            disabled={!isValid}
            title={
              isValid ? "Create your post" : "All fields must be filled out."
            }
          >
            Save
          </button>
        </div>

        <div className="containerEdit">
          <input
            className=""
            type="text"
            placeholder="Author"
            name="author"
            onChange={handleInputChange}
            value={newPost.author}
          />
          <input
            className=""
            type="text"
            placeholder="Content"
            name="content"
            onChange={handleInputChange}
            value={newPost.content}
          />
        </div>
      </form>
    </div>
  );
};

export default New;

CodeSandbox

CodePudding user response:

You can compare your input value to empty string like that :

inputValue === ''

or the size of the string :

inputValue.length === 0

And check the value in if statement with inside your submit.

CodePudding user response:

const createPost = (e) => {
    e.preventDefault()
    if (newPost.title !== '' && newPost.author !== '' && newPost.content !== '') {
        // make api request
    } else {
        // handle empty fields
    }
}

CodePudding user response:

You can validate the empty field inside createPost which should look something like:

 const createPost = (e: React.FormEvent<HTMLFormElement>) => {
     e.preventDefault(); //stop the form from reloading the page
        if (!newPost.title || !newPost.author || !newPost.content) {
           //show some error message
        } else {
           //perform further action
           setPost(newPost);
        }
    }

For a full working example click here.

  • Related