SOURCE

//自定义的hook
import { useState, useCallback } from 'react';

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

  // 验证函数:检查用户名是否为空
  const validateField = useCallback((fieldValue) => {
    if (!fieldValue || fieldValue.trim() === '') {
      return '用户名是必填项';
    }
    return ''; // 空字符串表示验证通过
  }, []);

  // 处理输入变化
  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;


//使用自定义的hook
import React from 'react';
import useName from './useName';

const NameForm = () => {
  // 使用自定义Hook
  const username = useName('');

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

  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="username"
            // 使用fieldProps便捷绑定
            {...username.fieldProps}
            style={{
              width: '100%',
              padding: '8px',
              border: username.error && username.touched ? '2px solid red' : '1px solid #ccc',
              borderRadius: '4px'
            }}
            placeholder="请输入用户名"
          />
          
          {/* 错误提示 */}
          {username.error && username.touched && (
            <span style={{ color: 'red', fontSize: '14px', marginTop: '5px', display: 'block' }}>
              ⚠️ {username.error}
            </span>
          )}
        </div>

        <button
          type="submit"
          style={{
            width: '100%',
            padding: '10px',
            backgroundColor: username.isValid ? '#007bff' : '#ccc',
            color: 'white',
            border: 'none',
            borderRadius: '4px',
            cursor: username.isValid ? 'pointer' : 'not-allowed'
          }}
          disabled={!username.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>{username.touched ? '是' : '否'}</strong></p>
        <p>是否有效: <strong>{username.isValid ? '是' : '否'}</strong></p>
        {username.error && <p>错误信息: <strong style={{color: 'red'}}>{username.error}</strong></p>}
      </div>

      {/* 重置按钮 */}
      <button
        onClick={username.reset}
        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