SOURCE

//增加身份证校验规则
import { useState, useCallback } from 'react';

// 自定义Hook:表单验证
const useName = (initialValue = '', type='') => {
  // 状态管理:字段值和错误信息
  const [value, setValue] = useState(initialValue);
  const [error, setError] = useState('');
  const [touched, setTouched] = useState(false);

  // 验证函数:检查是否为空
  const validateField = useCallback((fieldValue) => {
    if (!fieldValue || fieldValue.trim() === '') {
      return '请输入必填项';
    }
    //如果是身份证号码,进行身份证号校验:15位纯数字或18位(前17位数字 + 最后一位数字 or X or x)
    if(type="certNo") {
       const certNoReg = /^(?:\d{15}|\d{17}[\dXx])$/
       if(!certNoReg.test(fieldValue.trim())){
         return '身份证号码格式不正确';
       }
    }
   
    return ''; // 空字符串表示验证通过
  }, [type]);

  // 处理输入变化
  const handleChange = useCallback((e) => {
    const newValue = e.target.value;
    setValue(newValue);
    
    // 如果字段已经被触摸过,实时验证
    if (touched) {
      const validationError = validateField(newValue);
      setError(validationError);
    }
  }, [touched, validateField]);

  // 处理失去焦点事件
  const handleBlur = useCallback(() => {
    setTouched(true);
    const validationError = validateField(value);
    setError(validationError);
  }, [value, validateField]);

  // 手动验证函数(可用于提交前验证)
  const validate = useCallback(() => {
    setTouched(true);
    const validationError = validateField(value);
    setError(validationError);
    return validationError === ''; // 返回布尔值表示是否有效
  }, [value, validateField]);

  // 重置字段
  const reset = useCallback(() => {
    setValue(initialValue);
    setError('');
    setTouched(false);
  }, [initialValue]);

  // 返回给组件使用的API
  return {
    // 状态
    value,
    error,
    touched,
    isValid: error === '', // 便捷的有效性检查
    
    // 方法
    handleChange,
    handleBlur,
    validate,
    reset,
    setValue,
    
    // 便捷的对象展开(用于直接绑定到input)
    fieldProps: {
      value,
      onChange: handleChange,
      onBlur: handleBlur,
    }
  };
};

export default useName;


import React from 'react';
import useField from './useName';

const NameForm = () => {
  // 使用自定义Hook
  const userName  = useField('','userName');
  const certNo = useField('','certNo');

  const handleSubmit = (e) => {
    e.preventDefault();
    
    // 提交前进行最终验证
    const isValid = userName.validate();
    const isCertNoValid = certNo.validate();
    
    if (isValid && isCertNoValid) {
      // 验证通过,处理提交逻辑
      alert(`用户名 "${userName.value}" ,身份证号"${certNo.value}"验证通过!`);
    } else {
      console.log('表单有错误,请检查');
    }
  };
  const handleReset = () =>{
    userName.reset();
    certNo.reset();
  }

  return (
    <div style={{ maxWidth: '400px', margin: '50px auto', padding: '20px' }}>
      <h2>用户验证示例</h2>
      
      <form onSubmit={handleSubmit}>
        <div style={{ marginBottom: '20px' }}>
          <label htmlFor="userName" style={{ display: 'block', marginBottom: '5px' }}>
            用户名:
          </label>
          
          <input
            type="text"
            id="useruserNamename"
            // 使用fieldProps便捷绑定
            {...userName.fieldProps}
            style={{
              width: '100%',
              padding: '8px',
              border: userName.error && userName.touched ? '2px solid red' : '1px solid #ccc',
              borderRadius: '4px'
            }}
            placeholder="请输入用户名"
          />
          
          {/* 错误提示 */}
          {user.error && userName.touched && (
            <span style={{ color: 'red', fontSize: '14px', marginTop: '5px', display: 'block' }}>
              ⚠️ {userName.error}
            </span>
          )}
        </div>
        <div style={{ marginBottom: '20px' }}>
          <label htmlFor="certNo" style={{ display: 'block', marginBottom: '5px' }}>
            身份证号:
          </label>
          
          <input
            type="text"
            id="certNo"
            // 使用fieldProps便捷绑定
            {...certNo.fieldProps}
            style={{
              width: '100%',
              padding: '8px',
              border: certNo.error && certNo.touched ? '2px solid red' : '1px solid #ccc',
              borderRadius: '4px'
            }}
            placeholder="请输入身份证号码"
          />
          
          {/* 错误提示 */}
          {certNo.error && certNo.touched && (
            <span style={{ color: 'red', fontSize: '14px', marginTop: '5px', display: 'block' }}>
              ⚠️ {certNo.error}
            </span>
          )}
        </div>

        <button
          type="submit"
          style={{
            width: '100%',
            padding: '10px',
            backgroundColor: certNo.isValid ? '#007bff' : '#ccc',
            color: 'white',
            border: 'none',
            borderRadius: '4px',
            cursor: certNo.isValid ? 'pointer' : 'not-allowed'
          }}
          disabled={!certNo.isValid}
        >
          提交
        </button>
      </form>

      {/* 调试信息 */}
      <div style={{ 
        marginTop: '30px', 
        padding: '15px', 
        backgroundColor: '#f5f5f5', 
        borderRadius: '4px',
        fontSize: '14px'
      }}>
        <h4>调试信息:</h4>
        <p>用户名: <strong>"{userName.value}"</strong></p>
        <p>身份证号: <strong>"{certNo.value}"</strong></p>
      </div>

      {/* 重置按钮 */}
      <button
        onClick={handleReset}
        style={{
          marginTop: '10px',
          padding: '8px 16px',
          backgroundColor: '#6c757d',
          color: 'white',
          border: 'none',
          borderRadius: '4px',
          cursor: 'pointer'
        }}
      >
        重置表单
      </button>
    </div>
  );
};

export default NameForm;
console 命令行工具 X clear

                    
>
console