Day12-React 表单验证篇-使用 Custom hook 进行表单的验证

这次我们使用 Custom hook 进行表单的验证。

首先我们建立一个档案叫 useInputValidate.js ,里面将会写一个 Custom hook,分两个部分完成。

第一步

先写出 hook 的函式,并产生 state,这里使用 useReducer 管理 state。

此 hook 接受一个参数 validateValue,因为不同的输入内容验证输入有效的方式也会不同,所以就把验证的函式做为参数传入。

const initialInput = {
  value: '',
  isTouched: false,
};

const inputReducer = (state, action) => {
  switch (action.type) {
    case "INPUT":
      return { value: action.value, isTouched: state.isTouched };
    case "BLUR":
      return { isTouched: true, value: state.value };
    case "Reset":
      return { isTouched: false, value: '' };
    default:
      return state;
  }
}

const useInputValidate = (validateValue) => {
  const [input, dispatch] = useReducer(inputReducer, initialInput);
}

第二步

加上相关的事件函式及回传值就完成此 hook。

const initialInput = {
  value: "",
  isTouched: false
};

const inputReducer = (state, action) => {
  switch (action.type) {
    case "INPUT":
      return { value: action.value, isTouched: state.isTouched };
    case "BLUR":
      return { isTouched: true, value: state.value };
    case "Reset":
      return { isTouched: false, value: "" };
    default:
      return state;
  }
};

const useInputValidate = (validateValue) => {
  const [input, dispatch] = useReducer(inputReducer, initialInput);

  const valueIsValid = validateValue(input.value);
  const hasError = !valueIsValid && input.isTouched;

  const onChangeValue = (e) => {
    dispatch({ type: "INPUT", value: e.target.value });
  };

  const onBlurValue = () => {
    dispatch({ type: "BLUR" });
  };

  const reset = () => {
    dispatch({ type: "RESET" });
  };

  return {
    value: input.value,
    isValid: valueIsValid,
    hasError,
    onChangeValue,
    onBlurValue,
    reset
  };
};

实际使用

接着我们来实际使用一下这个 hook,将 hook 回传的内容进行解构赋值,加到会用到它们的地方即可。

另外记得给 hook 一个函式当作参数,用来验证输入值用。

import "./styles.css";

import useInputValidate from "./useInputValidate";

const emailRule = /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z]+$/;
const isNotEmpty = (value) => value.trim() !== "";
const isEmailFormat = (value) => emailRule.test(value);

const SimpleForm = () => {
  const {
    value: name,
    isValid: nameIsValid,
    hasError: nameError,
    onChangeValue: onChangeName,
    onBlurValue: onBlurName,
    reset: resetName
  } = useInputValidate(isNotEmpty);

  const {
    value: email,
    isValid: emailIsValid,
    hasError: emailError,
    onChangeValue: onChangeEmail,
    onBlurValue: onBlurEmail,
    reset: resetEmail
  } = useInputValidate(isEmailFormat);

  const onFormSubmit = (e) => {
    e.preventDefault();

    if (!nameIsValid || !emailIsValid) {
      return;
    }

    console.log("submit success!");
    console.log(name, email);

    // reset
    resetName();
    resetEmail();
  };

  const nameInputClasses = nameError ? "invalid" : "";
  const emailInputClasses = emailError ? "invalid" : "";

  return (
    <form onSubmit={onFormSubmit}>
      <label htmlFor="name">Your Name</label>
      <input
        type="text"
        id="name"
        onChange={onChangeName}
        onBlur={onBlurName}
        value={name}
        className={nameInputClasses}
      />
      {nameError && <p className="error-text">Name must not be empty.</p>}
      <label htmlFor="email">Your E-Mail</label>
      <input
        type="email"
        id="email"
        onChange={onChangeEmail}
        onBlur={onBlurEmail}
        value={email}
        className={emailInputClasses}
      />
      {emailError && <p className="error-text">Please enter a valid email.</p>}
      <button disabled={!nameIsValid || !emailIsValid}>Submit</button>
    </form>
  );
};

export default SimpleForm;

程序码范例(codesandbox)

透过以上的方式,如果表格栏位一多的时候,就不用再写许多相似的程序码,让整个表单元件的程序码变得更加可读。


<<:  Day26:河内塔(Tower of Hanoi)

>>:  抓取阅览人数

[Day 14] 回测分析

什麽是回测? 在金融领域,回测通过测试交易策略,并根据历史资料的表现来核查其可行性。换句话说,它使用...

Swift 新手-ios 应用软件开发资料与云端储存篇(二)

使用 Firebase 专案串接 GA4 资源,提升 App 绩效 过往无法一探究竟的技术过程,现在...

D1 (9/1)-全家(5903),统一超(2912)

注:发文日和截图的日期不一定是同一天。 买进全家(5903)、统一超(2912) 今日损益:-7 原...

Day 15 Models介绍

Odoo模组开发实战 目录 1.models介绍 2.常用的模型属性 第一章 models介绍 第二...

[day4]API串接-安全签章Sign(一) 发现昨天上传失败,残念

噩耗~早上起床发现昨天上传没成功,铁人中断了!!不过还是继续写下去吧! 中秋节连假第二天,今天开始串...