簡體   English   中英

反應 useState 鈎子:object 屬性保持不變

[英]React useState hook: object property remains unchanged

我最近開始學習 react 並且我有一個包含登錄表單的組件:

import Joi from "joi";
import { useState } from "react";

const Login = () => {
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");
  const loginSchema = Joi.object().keys({
    username: Joi.string().required(),
    password: Joi.string().required(),
  });
  const [errors, setErrors] = useState({ username: null, password: null });

  const handleSubmit = (form) => {
    form.preventDefault();
    validate();
  };

  const validate = () => {
    const { error } = loginSchema.validate(
      { username, password },
      { abortEarly: false }
    );
    if (!error) return null;
    for (const item of error.details) {
      let key = item.path[0];
      let value = item.message;
      setErrors({ ...errors, [key]: value });
    }
    return errors;
  };

  return (
    <div className="container">
      <div>
        <h1>Login</h1>
      </div>
      <div className="card">
        <div className="card-body">
          <form onSubmit={handleSubmit}>
            <div className="form-group">
              <label htmlFor="username">Username</label>
              <input
                name="username"
                type="text"
                className="form-control"
                id="username"
                placeholder="Enter username"
                value={username}
                onChange={(username) => setUsername(username.target.value)}
              />
              {errors.username && (
                <div className="alert alert-danger">{errors.username}</div>
              )}
            </div>
            <div className="form-group">
              <label htmlFor="password">Password</label>
              <input
                name="password"
                type="password"
                className="form-control"
                id="password"
                placeholder="Password"
                value={password}
                onChange={(password) => setPassword(password.target.value)}
              />
              {errors.password && (
                <div className="alert alert-danger">{errors.password}</div>
              )}
            </div>
            <button type="submit" className="btn btn-primary">
              Submit
            </button>
          </form>
          {/* Delete later */}
          <h4>{JSON.stringify(errors)}</h4>
        </div>
      </div>
    </div>
  );
};

export default Login;

在這里,我試圖在錯誤 object 中設置用戶名和密碼的值,但由於某種原因,只設置了密碼屬性,用戶名屬性仍然是 null。 我已經使用 object 解構但它仍然沒有設置值,請幫助。

我認為問題來自這段代碼

for (const item of error.details) {
  let key = item.path[0];
  let value = item.message;
  setErrors({ ...errors, [key]: value });
}

在這里,您在 for 循環中調用setErrors時出現相同的errors object 因此只考慮最后一個字段。

這是一個可能的解決方案:

if (!error) return null;

const newErrors = error.details.reduce((acc, item) => {
  const key = item.path[0];
  const value = item.message;
  acc[key] = value;
  return acc;
}, {...errors});

setErrors(newErrors);

State 更新不會立即反映在 React 中,並且由於您循環數據以設置錯誤 object 多次,由於事件處理程序中的批處理以及 Z9ED39E2EA9312586B6AZ85E 更新受閉包影響的事實,它僅設置在最后一個鍵中。

您應該創建一個更新的對象並將其設置在 state 一次

   let newErrors = {};
   for (const item of error.details) {
      let key = item.path[0];
      let value = item.message;
      newErrors = { ...newErrors, [key]: value };
    }
  setErrors(prev => ({...prev, ...newErrors}));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM