【问题标题】:React useState hook: object property remains unchangedReact useState hook:对象属性保持不变
【发布时间】:2021-05-01 09:57:21
【问题描述】:

我最近开始学习 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;

在这里,我试图在错误对象中设置用户名和密码的值,但由于某种原因,只设置了密码属性,用户名属性保持为空。我使用了对象解构,但它仍然没有设置值,请帮助。

【问题讨论】:

    标签: javascript reactjs use-state object-destructuring


    【解决方案1】:

    状态更新不会立即反映在 React 中,并且由于您循环数据以多次设置错误对象,由于事件处理程序中的批处理以及状态更新受闭包影响的事实,它仅设置在最后一个键中.

    您应该创建一个更新的对象并将其设置为一次状态

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

    【讨论】:

    • 那行得通。我不知道如果使用 for 循环,只有最后一个键被设置。谢谢你的回答。
    【解决方案2】:

    我认为问题出在这段代码

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

    在这里,您在 for 循环中使用相同的 errors 对象调用 setErrors,因此只考虑最后一个字段。

    这是一个可能的解决方案:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-02
      • 1970-01-01
      • 2021-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多