首页 > 解决方案 > 带有钩子的函数组件中的数组未在 React 状态下更新

问题描述

我正在探索表单验证并在 State 中有一个 validationMessages 数组来存储验证消息。当用户提交表单时,我运行验证并尝试更新 State 中的 validationMessages 数组。但是只添加了最后一个validationMessage,而没有添加之前的validationMessage。代码如下:

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 上查看类似问题及其答案,也无法弄清楚。任何指针或帮助表示赞赏。

标签: reactjsreact-hooksreact-state

解决方案


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

推荐阅读