Массив не обновляется в React State в компоненте функции с перехватчиками - PullRequest
0 голосов
/ 24 апреля 2020

Я изучаю проверку формы и имею массив validationMessages в State для хранения сообщений проверки. Когда пользователь отправляет форму, я запускаю проверку и пытаюсь обновить массив validationMessages в State. Но добавляется только последнее сообщение проверки, а предыдущие нет. Код выглядит следующим образом:

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;  

Проблема заключается в том, что если я оставлю все поля пустыми, тогда в массив состояний validationMessages будет добавлено только последнее сообщение проверки. Невозможно понять это, даже потратив немало времени на просмотр похожих вопросов и их ответов здесь, на StackOverflow.com. Любые указатели или помощь приветствуется.

1 Ответ

1 голос
/ 24 апреля 2020

В вашем validateForm вы вызываете setValidationMessages несколько раз, чтобы добавить сообщение в массив состояний. Но setValidationMessages является асинхронным, поэтому второй вызов не будет иметь новую версию validationMessages, и поэтому только последнее сообщение будет сохранено в состоянии

Вот возможное решение:

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);
}
...