热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

React表单验证:构建无第三方库的表单处理机制

本文将深入探讨如何在不依赖第三方库的情况下,使用React处理表单输入和验证。我们将介绍一种高效且灵活的方法,涵盖表单提交、输入验证及错误处理等关键功能。

在现代 Web 应用程序中,表单处理是一个常见的需求。本文将展示如何仅使用 React 实现强大的表单验证,而无需引入额外的第三方库。

概述

我们将创建一个自定义的表单管理解决方案,涵盖以下主要功能:

  • 通过 onSubmit 回调处理表单提交。
  • 对单个输入进行前端验证。
  • 在表单提交时进行验证,而不是在失去焦点时。
  • 提供重置表单的功能。

工作原理

我们利用 React 的上下文(Context)API 来管理表单状态,并确保所有输入组件都能访问和更新这些状态。具体步骤如下:

  1. 创建一个表单上下文,用于保存所有输入的状态和验证逻辑。
  2. 当输入组件加载时,它们会向表单上下文注册自己,并传递必要的信息。
  3. 输入值发生变化时,更新表单上下文中的状态。
  4. 提交表单时,运行所有已注册的验证器,并根据结果设置错误消息。

下图展示了不同组件之间的交互:

组件职责图

实现细节

表单状态结构

表单状态需要存储以下三类信息:

  • 用户输入的数据。
  • 每个字段的验证规则。
  • 特定字段的错误消息。

我们可以使用一个对象来表示这些信息:

const FORM_STATE = { data: {}, validators: {}, errors: {} };

每个输入必须有一个唯一的名称属性,以便在状态结构中作为键使用。

表单上下文

为了将表单状态和方法注入到各个输入组件中,我们使用了上下文提供者模式。这样可以确保所有子组件都可以轻松访问表单状态。

此外,我们还创建了一个高阶组件(HOC),用于封装上下文订阅逻辑,从而使输入组件保持纯粹的 UI 层。

表单方法

接下来,我们将详细介绍表单上下文的主要行为。

注册与注销

每当输入组件加载时,它会在表单上下文中注册自己,并复制其验证规则。卸载时,清除相关数据和验证规则。

const registerInput = ({ name, validators }) => { setFormState(state => ({ ...state, validators: { ...state.validators, [name]: validators || [] }, errors: { ...state.errors, [name]: [] } })); return () => { setFormState(state => { const { data, errors, validators: currentValidators } = { ...state }; delete data[name]; delete errors[name]; delete currentValidators[name]; return { data, errors, validators: currentValidators }; }); }; };

控制输入数据

对于受控输入,我们通过 onChange 事件更新表单上下文中的数据,并清除任何现有错误。

const setFieldValue = (name, value) => { setFormState(state => ({ ...state, data: { ...state.data, [name]: value }, errors: { ...state.errors, [name]: [] } })); };

提交与验证

当用户点击提交按钮时,系统会遍历所有验证器,并检查是否有任何错误。如果有错误,则更新错误状态;否则,调用 onSubmit 回调。

const validate = () => { setFormState(state => ({ ...state, errors: {} })); if (isEmpty(validators)) { return true; } const formErrors = Object.entries(validators).reduce((errors, [name, validators]) => { const messages = validators.reduce((result, validator) => { const value = formState.data[name]; const err = validator(value, formState.data); return [...result, ...err]; }, []); if (messages.length > 0) { errors[name] = messages; } return errors; }, {}); if (isEmpty(formErrors)) { return true; } setFormState(state => ({ ...state, errors: formErrors })); return false; };

请注意,我们一次性收集所有错误,以避免用户在修复多个错误时反复提交表单。

高级特性:包装输入组件

为了简化输入组件的开发,我们创建了一个高阶组件(HOC),用于自动处理输入注册、错误显示等功能。

import React, { useContext, useEffect } from 'react'; import PropTypes from 'prop-types'; import { FormContext } from './index'; const withForm = InputCompOnent=> { const WrappedWithForm = props => { const { errors, data, setFieldValue, registerInput } = useContext(FormContext); useEffect(() => registerInput({ name: props.name, validators: props.validators }), []); const OnChange= val => { setFieldValue(props.name, val); if (props.onChange) { props.onChange(val); } }; const inputValue = data[props.name]; const inputErrors = errors[props.name] || []; return ; }; WrappedWithForm.propTypes = { name: PropTypes.string.isRequired, validators: PropTypes.arrayOf(PropTypes.func) }; return WrappedWithForm; }; export default withForm;

完整示例:注册表单

最后,让我们看看一个完整的注册表单示例:

 console.log(data)}>     

我们添加了一些简单的验证器,例如必填字段验证:

const requiredValidator = val => { if (!val) { return ["This field is required"]; } return []; };

您可以尝试点击提交和重置按钮,观察其工作原理。

感谢阅读!希望这篇文章能帮助您更好地理解如何在 React 中处理表单验证。如果您有任何问题或建议,请随时留言。

行动中的形式


推荐阅读
author-avatar
贷款喝稀饭
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有