2

I'm trying to validate the input of name and age. Neither can be empty and age should be over 0. https://codesandbox.io/s/agitated-microservice-g5lys?file=/src/App.js

I tried with two ways.

Solution 1: Add a validation at error message. Problem: at initial loading before user input, the error message is already shown.

{!enteredName ? <span> error msg: Please enter your first name</span> : null}

Solution 2: Add a validation inside the onsubmit handler function. Problem: not sure how to append the error message .

if (enteredName.trim().length === 0 || enteredAge.trim().length === 0) {
    return;
}
if (enteredAge < 0) {
    return;
}

Additional question: If i fuse solution 2 validation to solution 1, it'd be too long. How to wrap it in a separate function and attach it to solution 1?

Here's the entire code including both attempts.

import { useState } from "react";
    
function App() {
    const [enteredName, setEnteredName] = useState("");
    const [enteredAge, setEnteredAge] = useState("");
    const [submittedUsers, setSubmittedUsers] = useState([]);

    const nameChangeHandler = (event) => {
        setEnteredName(event.target.value);
    };
    const ageChangeHandler = (event) => {
        setEnteredAge(event.target.value);
    };

    const submittedHandler = (event) => {
        event.preventDefault();

        // Solution 1
        //validate if input is empty? validate age above 0?
        if (enteredName.trim().length === 0 || enteredAge.trim().length === 0) {
            return null;
        }
        if (enteredAge < 0) {
            return null;
        }

        // lift up state
        setSubmittedUsers([
            ...submittedUsers,
            {
                name: enteredName,
                age: enteredAge,
                id: Math.random().toString()
            },
        ]);
        console.log(submittedUsers);

        setEnteredName("");
        setEnteredAge("");
    };

    return (
        <div className="App">
            <header className="App-header">
                <h3>
                    <ul>
                        <li>Display user input </li>
                        <li>Validate user input</li>
                    </ul>
                </h3>

                <form onSubmit={submittedHandler}>
                    <input
                        placeholder="your name"
                        value={enteredName}
                        type="text"
                        onChange={nameChangeHandler}
                    />
                    <br />
                    {/* Solution 2 */}
                    {!enteredName ? <span>error msg:  Please enter your first name</span> : null}
                    <br />
                    <br />

                    <input
                        placeholder="your age (number > 0)"
                        type="number"
                        value={enteredAge}
                        onChange={ageChangeHandler}
                    />
                    <br />
                    {!enteredAge ? <span> error msg: Please enter a valid age</span> : null}
                    <br />
                    <button>Submit</button>

                    <h3>
                        User input:
                        <ul>
                            {submittedUsers.map((u) => (
                                <li key={u.id}>
                                    {u.name} ({u.age} years old)
                                </li>
                            ))}
                        </ul>
                    </h3>
                </form>
            </header>
        </div>
    );
}

export default App;
2
  • 1
    I would suggest to use third party like formik. For smaller inputs maybe your implementation works but if your inputs increased with time its hard to handle manually. That's why these packages are there Commented Oct 25, 2021 at 14:01
  • im trying to avoid any external lib in order to grasp the core of how basic things work. but thanks Commented Oct 25, 2021 at 14:02

2 Answers 2

3

If you use <form>, you can set onInvalid setCustomValidity for your <input>. You'll also need to set make your input required or add a pattern. You'll achieve something like this:

enter image description here

Example:

<input
   placeholder="your name"
   value={enteredName}
   type="text"
   onChange={nameChangeHandler}
   required
   onInvalid={(e)=>{e.target.setCustomValidity("error msg:  Please enter your first name")}}
/>

And in you nameChangeHandler you'll need to reset validity:

const nameChangeHandler = (event) => {
    setEnteredName(event.target.value);
    event.target.setCustomValidity("");
};

As for age input try to set min and max property.

Sign up to request clarification or add additional context in comments.

1 Comment

Exactly what I needed. This also works if you're using the field pattern
1

You can have a default error that is only displayed when the error happens, this means when you validate the input, if it's incorrect you set your errorValue to true.

Like so:

First declare the error value

const [error, setError] = useState(false);

Then tweak your validation process:

  const submittedHandler = (event) => {
        event.preventDefault();

        // Solution 1
        //validate if input is empty? validate age above 0?
        if (enteredName.trim().length === 0 || enteredAge.trim().length === 0) {
        SetError(true)
            return null;
        }

And then make a conditional display of the error only if the value is set to true:

{error && 
                <span className='error'>Your error message here</span>}

Note that you can make the condition vary if, for instance, you want your name to be at least 5 char long or any other pre-requisite.

3 Comments

there's a small problem with this solution. after i submit a form successfully, the inputs are set to " ", and it triggers the error msg
another problem, when one field is missing, both error msgs show up
To prevent all error message to be shown when only one statement is false, you can put your errors in an array and then make the conditional display check the value of the cell in the array.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.