0

I am exploring Form validation and have a validationMessages array in State to store validation messages. When the user submits the form, I run validation and try to update the array of validationMessages in State. But only the last validationMessage is added and the previous ones are not. The code is as follows:

import React, { useState } from 'react';

function Form(props) {
    const [validationMessages, setValidationMessages] = useState([]);
    const [formData, setFormData] = useState({});
    const handleChange = ({ target }) => {
        setFormData({ ...formData, [target.name]: target.value });
    }
    const handleClick = (evt) => {
        validateForm();
        if (validationMessages.length > 0) {
            evt.preventDefault();
        }
    }
    const validateForm = () => {
        const { firstName, lastName, DOB, gender } = formData;
        setValidationMessages([]);
        if (!firstName) {
            setValidationMessages([...validationMessages, "First Name is required"]);
        }
        if (!lastName) {
            setValidationMessages([...validationMessages, "Last Name is required"]);
        }
        if (!gender) {
            setValidationMessages([...validationMessages, "Please select a Gender"]);
        }
        if (!DOB) {
            setValidationMessages([...validationMessages, "Date of Birth is required"]);
        }
    }
    return <div style={{ display: 'flex', flexDirection: 'row' }} >
        <form style={{ display: 'flex', flexDirection: 'column' }}>
            <label>First Name</label>
            <input value={formData.firstName || ''} onChange={handleChange} type="text" name="firstName" />
            <label>Last Name</label>
            <input value={formData.lastName || ''} onChange={handleChange} type="text" name="lastName" />
            <label>Date of Birth</label>
            <input value={formData.DOB || ''} onChange={handleChange} type="datetime-local" name="DOB" />
            <label>Gender</label>
            <div><input value="Male" checked={formData.gender === "Male"} onChange={handleChange} type="radio" name="gender" />Male</div>
            <div><input value="Female" checked={formData.gender === "Female"} onChange={handleChange} type="radio" name="gender" />Female</div>
            <div><input value="None" checked={formData.gender === "None"} onChange={handleChange} type="radio" name="gender" />Prefer not to say</div>
            <button type="button" onClick={handleClick}>Save</button>
        </form><div>{validationMessages.length > 0 && <span>Validation Summary</span>}
            <ul>
                {validationMessages.map(vm => <li key={vm}>{vm}</li>)}
            </ul></div></div>;
}

export default Form;  

The issue is if I leave all fields blank then still only the last validation message is added to the state array of validationMessages. Unable to figure it out even after spending quite a bit of time looking at similar questions and their answers here on StackOverflow.com. Any pointers or help is appreciated.

1

1 Answer 1

1

In your validateForm, you call setValidationMessages several times to add a message to the state array. But setValidationMessages is asynchronous, so the second call won't have the new version of validationMessages and therefore only the last message will be saved to state

Here is a possible solution:

const validateForm = () => {
    const { firstName, lastName, DOB, gender } = formData;
    const messages = [];
    if (!firstName) {
        messages.push("First Name is required");
    }
    if (!lastName) {
        messages.push"Last Name is required");
    }
    if (!gender) {
        messages.push("Please select a Gender");
    }
    if (!DOB) {
        messages.push("Date of Birth is required");
    }
    setValidationMessages(messages);
}
Sign up to request clarification or add additional context in comments.

Comments

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.