如何在此 React 18 应用程序中即时验证表单字段?

2024-03-02

我正在使用 React 18 和 Firebase 开发一个聊天应用程序。

In the src\pages\Register.jsx组件,我有一个可以验证的表单简单的身体验证器 https://github.com/jadKhoury1/simple-body-validator:

import React, { useState } from "react";
import FormCard from '../components/FormCard/FormCard';
import { make } from 'simple-body-validator';

export default function Register() {
 const initialFormData = {
    firstName: '',
    lastName: '',
    email: '',
    password: '',
    passwordConfirm: ''
 };

 const validationRules = {
    firstName: ['required', 'string', 'min:3', 'max:255'],
    lastName: ['required', 'string', 'min:3', 'max:255'],
    email: ['required', 'email'],
    password: ['required', 'confirmed'],
    passwordConfirm: ['required'],
 };

 const validator = make(initialFormData, validationRules);
 const [formData, setFormData] = useState(initialFormData);
 const [errors, setErrors] = useState(validator.errors());

 const handleChange = (event) => {
    const { name, value } = event.target;
    setFormData((prevFormData) => ({ ...prevFormData, [name]: value }));
  };

 const handleSubmit = (event) => {
    event.preventDefault();

    if (!validator.setData(formData).validate()) {
      setErrors(validator.errors());
    }
 };
  
 return (
    <FormCard title="Register">
      <form onSubmit={handleSubmit}>
        <div className={`mb-2 form-element ${errors.has('firstName') ? 'has-error' : null}`}>
          <label for="firstName" className="form-label">First name</label>
          <input type="text" id="firstName" name="firstName" value={formData.firstName} onChange={handleChange} className="form-control form-control-sm" />
          { errors.has('firstName') ? (
          <p className="invalid-feedback">{errors.first('firstName')}</p>
        ) : null }
        </div>

        <div className={`mb-2 form-element ${errors.has('lastName') ? 'has-error' : null}`}>
          <label for="lastName" className="form-label">Last name</label>
          <input type="text" id="lastName" name="lastName" value={formData.lastName} onChange={handleChange} className="form-control form-control-sm" />
          { errors.has('lastName') ? (
          <p className="invalid-feedback">{errors.first('lastName')}</p>
        ) : null }
        </div>

        <div className={`mb-2 form-element ${errors.has('email') ? 'has-error' : null}`}>
          <label for="email" className="form-label">Email address</label>
          <input type="email" id="email" name="email" value={formData.email} onChange={handleChange} className="form-control form-control-sm" />
          { errors.has('email') ? (
          <p className="invalid-feedback">{errors.first('email')}</p>
        ) : null }
        </div>

        <div className={`mb-2 form-element ${errors.has('password') ? 'has-error' : null}`}>
          <label for="password" className="form-label">Password</label>
          <input type="password" id="password" name="password" value={formData.password} onChange={handleChange} className="form-control form-control form-control-sm" />
          { errors.has('password') ? (
          <p className="invalid-feedback">{errors.first('password')}</p>
        ) : null }
        </div>

        <div className={`mb-2 form-element ${errors.has('passwordConfirm') ? 'has-error' : null}`}>
          <label for="password_repeat" className="form-label">Confirm Password</label>
          <input type="password" id="passwordConfirm" name="passwordConfirm" value={formData.passwordConfirm} onChange={handleChange} className="form-control form-control form-control-sm" />
          { errors.has('passwordConfirm') ? (
          <p className="invalid-feedback">{errors.first('passwordConfirm')}</p>
        ) : null }
        </div>

        <div className="pt-1">
          <button type="submit" className="btn btn-sm btn-success fw-bold">Submit</button>
        </div>
      </form>
    </FormCard>
  );
 }

如果表单无效,一旦提交成功,验证错误消息将按预期显示:

问题

如果将有效数据引入无效表单,则验证错误消息和类不会在输入/更改时消失,正如我认为应该的那样。

有效字段仅在再次单击提交按钮时才通过验证虽然我希望得到反馈instant,类似于 AngularJS 或 Angular2+ 形式。

Sandbox

有一个包含代码的沙箱here https://codesandbox.io/s/infallible-cloud-wmf2jn。报名途径是/auth/register.

问题

  1. 我究竟做错了什么?
  2. 获得所需行为的最可靠方法是什么?

我注意到您使用的库不处理表单状态(例如脏的、原始的)。

所以,这是我的方法:

注册.tsx

/* ... */
const initialFormData = {
  firstName: "",
  lastName: "",
  email: "",
  password: "",
  passwordConfirm: ""
};

const [pristineFields, setPristineFields] = useState(() =>
  Object.keys(initialFormData)
);

const handleChange = (event) => {
  const { name, value } = event.target;

  setFormData((prevFormData) => {
    const newFormData = { ...prevFormData, [name]: value };
    const newPristineFields = pristineFields.filter((f) => f !== name);

    validator.setData(newFormData).validate();
    const validationErrors = validator.errors();
    // 'Forgetting' about pristine fields.
    newPristineFields.forEach((f) => validationErrors.forget(f));
    setErrors(validationErrors);

    setPristineFields(newPristineFields);

    return newFormData;
  });
};

/* ... */

我还在以下内容中添加了这些行submit处理程序:

const handleSubmit = (event) => {
  event.preventDefault();

  if (!validator.setData(formData).validate()) {
    setErrors(validator.errors());
  } else {
    console.log("all good");
  }

  // Validations are shown either way, so we could forget
  // about any pristine fields at this point.
  setPristineFields([]);
};

Here https://codesandbox.io/s/funny-parm-h52ync?file=/src/pages/Register.jsx是更新的 CodeSandbox 应用程序的链接。


更新 - 验证/无效确认密码

const CONFIRM_PASSWORD_KEY = "passwordConfirm";
const PASSWORD_KEY = "password";

export default function Register() {
  const initialFormData = {
    firstName: "",
    lastName: "",
    email: "",
    [PASSWORD_KEY]: "",
    [CONFIRM_PASSWORD_KEY]: ""
  };
...

然后,在setFormData的回调中,我添加了密码确认的逻辑:

...
    setFormData((prevFormData) => {
      const newFormData = { ...prevFormData, [name]: value };
      const newPristineFields = pristineFields.filter((f) => f !== name);

      validator.setData(newFormData).validate();
      const validationErrors = validator.errors();
      newPristineFields.forEach((f) => validationErrors.forget(f));

      // Other cases can be handled here..
      if (name === CONFIRM_PASSWORD_KEY) {
        if (value !== newFormData[PASSWORD_KEY]) {
          validationErrors.add(CONFIRM_PASSWORD_KEY, {
            message: "Passwords do not match."
          });
        }
      }

      setErrors(validationErrors);
      setPristineFields(newPristineFields);
      return newFormData;
    });
...
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在此 React 18 应用程序中即时验证表单字段? 的相关文章

随机推荐

  • 改造响应保留旧数据并将新数据添加到 editText 搜索的数据中

    我正在使用 editText 搜索从 API 获取数据 第一次搜索时 它按预期工作 但在第二次搜索时 它不会显示唯一的新响应 而是保留旧响应并在其末尾添加新响应 它的行为就像缓存以前的一样 我该如何修复该问题以仅显示最后一个搜索词结果 分段
  • Google 云端硬盘文件列表:500 错误

    对于我们的应用程序 我们使用具有 2 足授权的 Google Drive SDK 我们使用 Drive SDK 很长时间了 但今天我们遇到了 Files list API 的新问题 https developers google com d
  • 用于一对多查找的 Cassandra 数据建模

    考虑存储用户及其联系人的问题 大约有一亿用户 每个用户有几百个联系人 平均联系人大小为 1kb 可能有些用户拥有太多联系人 gt 5000 并且可能有一些联系人比平均 1kb 大得多 例如 10 倍 用户会主动添加联系人 但很少会删除联系人
  • 使用 Ansible 配置 Jenkins 2.0

    我使用 Ansible 来配置我们的服务器 我安装了 Jenkins 2 0 但当我打开 Web UI 时 它变成了启动配置 我如何使用 Ansible 或 shell 或 jenkins cli 来做到这一点 CentOS 7 Ansib
  • 登录时从用户集合中获取用户数据

    我目前正在开发一个在客户端初始化了 firebase 的应用程序 当用户通过 firebase 登录时 我想从 firestore 获取用户的数据 我目前正在这样做onAuthStateChanged侦听器并成功获取用户 我想知道这是否是获
  • 套接字连接超时:规范在哪里?

    我的工作环境是我的局域网 下面的代码示例是用 Java 语言编写的 但我的问题是关于 TCP 而不是编程 我遇到过以下连接超时的情况 2 ms when connection established 当主机处于活动状态但未侦听指定套接字端口
  • emacs lisp 中的 let 和 flet

    我不知道你是否会称其为规范公式 但为了绑定本地函数 GNU 手册建议我使用 flet defun adder with flet x flet f x x 3 f x 然而 我偶然尝试了 在玩了一会儿Scheme之后 下面的表达式 其中我使
  • 将给定字符串转换为具有给定子字符串的回文

    给定字符串 S1 和字符串 S2 将字符串 S1 转换为回文字符串 例如 S2 是该回文字符串的子字符串 S1 上允许的唯一操作是将任何字符替换为任何其他字符 找出所需的最少操作次数 我已经编写了这段代码 可以计算需要使用常规字符串进行多少
  • AngularJS CORS 问题

    我已经搜索了 200 多个网站 也许有点夸张 但也不是很多 来了解如何使用 angularjs 处理 cors 我们有一台运行 Web API 服务器的本地计算机 我们正在开发一个调用 API 获取数据的客户端 当从服务器运行客户端时 我们
  • 计算多维数组中的元素数量

    我有这个代码 loadData function jsonArray var id this attr id for var i in jsonArray id tbody append tr class entry details pag
  • 声音匹配/搜索

    实际上声音匹配 搜索的当前技术水平如何 我目前正在远程参与规划一个 Web 应用程序 该应用程序将包含并公开录制的短音频剪辑 最多 3 5 秒 人名 的数据库 有人提出了是否有可能实现基于用户语音输入的搜索的问题 我的直觉告诉我 从计算和算
  • 如何在同一服务器环境下运行PHP和Tomcat?

    不久前在 AskUbuntu 上问过这个问题 https askubuntu com questions 630897 apache httpd backed by both tomcat and php https askubuntu c
  • TypeScript:类型“EventTarget & Element”上不存在属性“checked”。为什么它不存在?

    我收到此错误 错误 17 35 TS2339 类型 EventTarget Element 上不存在属性 checked 但这绝对是不可能的错误 因为 React 文档说checked确实存在于target的复选框 https reactj
  • 对复合对象数组以及日期范围进行 Elasticsearch 查询

    您好 我有一个问题 如何为具有日期范围和附加字段参数的嵌套复合对象创建弹性搜索查询 如下所示 name A availability partial true dates gte 2020 12 01 lte 2020 12 02
  • 在 Java 8 中使用 lambda 出现意外错误

    我正在使用 Java 8 Update 20 32 位 Maven 3 2 3 Eclipse Luna Build id 20140612 0600 32 位 开始使用 lambda 后 我的项目中的一些类开始在 Maven 中报告编译错
  • Javascript 前进后退按钮

    我在我正在开发的网站的主页上使用 s3Slider javascript 幻灯片 http alexisparkinn com http alexisparkinn com 我真的很喜欢这张幻灯片 但它无法让用户转到下一张或上一张图像 我怎
  • 有没有办法对VBA中的代码施加时间限制?

    我想知道是否有人有对代码段施加时间限制的经验 我已经用 VBA 将搜索引擎编程到 Excel 电子表格中 并且有一段代码可以删除重复的结果 现在 如果给出最模糊的搜索条件 这部分有时可能会持续相当长的时间 所以我想对这个操作施加一个时间限制
  • 使用滑块更改 QTimer 的间隔超时

    timer new QTimer this timer gt setInterval 50 QPushButton start new QPushButton Start Stop this start gt setText Start S
  • 使用 Core Data(在 SwiftUI 中)提供的数据并与另一个视图共享

    我在这里遇到了一些麻烦Core Data and SwiftUI 我的主视图可以访问来自实体的一些信息Core Data 我想使用某种绑定将其传递给子视图 以便它也可以访问该数据并可能更新它 这是我尝试过的代码的一个版本 在主视图一侧 En
  • 如何在此 React 18 应用程序中即时验证表单字段?

    我正在使用 React 18 和 Firebase 开发一个聊天应用程序 In the src pages Register jsx组件 我有一个可以验证的表单简单的身体验证器 https github com jadKhoury1 sim