背景

今天在写Nextjs代码的时候,发现一个问题,我使用react-use-form的表单,点击提交按钮的时候:onSubmit没有被触发!!

于是排查···

源代码如下:

  1. "use client"
  2. import { AddLinkRequest } from '@/app/api/link/add/route';
  3. import React, { useState } from 'react';
  4. import { useForm } from 'react-hook-form';
  5. import { FiCircle } from 'react-icons/fi';
  6. export default function AddLinkModal({ category, isOpen, onClose }: any) {
  7. const { register, handleSubmit, formState: { errors, isLoading } } = useForm();
  8. const onSubmit = async (data: any) => {
  9. console.log(data);
  10. console.log("cur data")
  11. // 构造更新类目请求体,从form里获取
  12. const newLinkData: AddLinkRequest = {
  13. title: '新分类',
  14. icon: 'https://cos.codefe.top/images/uinotes-icon.svg',
  15. description: '新分类的描述新分类的描述新分类的描述新分类的描述新分类的描述新分类的描述新分类的描述新分类的描述新分类的描述新分类的描述',
  16. userId: 0,
  17. rank: 0,
  18. url: 'https://cos.codefe.top/images/uinotes-icon.svg',
  19. categoryId: 3
  20. };
  21. try {
  22. const response = await addLink(newLinkData);
  23. if (!response.ok) {
  24. throw new Error(`${response.statusText}`);
  25. }
  26. const result = await response.json();
  27. console.log(result);
  28. onClose(); // 关闭弹窗
  29. } catch (error) {
  30. console.error('添加链接失败', error);
  31. }
  32. };
  33. if (!isOpen) return null;
  34. return (
  35. // eslint-disable-next-line tailwindcss/migration-from-tailwind-2
  36. <div className="/50 fixed inset-0 z-50 flex items-center justify-center bg-gray-600 bg-opacity-80">
  37. <div className=" rounded bg-white p-2 shadow-lg md:p-5">
  38. <div className="modal-header mb-4 flex items-center justify-between">
  39. <h3 className="text-lg font-semibold text-gray-900">新Link</h3>
  40. <button onClick={() => {
  41. onClose()
  42. }} className="text-md w-6 rounded-sm bg-slate-200 hover:bg-slate-500 focus:outline-none">
  43. <span aria-hidden="true">x</span>
  44. </button>
  45. </div>
  46. <form onSubmit={handleSubmit(onSubmit)} >
  47. <div className="mb-4">
  48. <label className="mb-2 block text-sm font-bold " htmlFor="category">
  49. 类别
  50. </label>
  51. <input
  52. id="category"
  53. disabled={true}
  54. value={category.title}
  55. className="focus:shadow-outline w-full appearance-none rounded border px-3 py-2 leading-tight shadow focus:outline-none"
  56. {...register('category', { required: true })}
  57. ></input>
  58. </div>
  59. <div className="mb-4">
  60. <label className="mb-2 block text-sm font-bold " htmlFor="title">
  61. 名称
  62. </label>
  63. <input
  64. type="text"
  65. {...register('title', { required: true })}
  66. id="title"
  67. className="focus:shadow-outline w-full appearance-none rounded border px-3 py-2 leading-tight shadow focus:outline-none"
  68. required
  69. />
  70. </div>
  71. <div className="mb-4">
  72. <label className="mb-2 block text-sm font-bold " htmlFor="url">
  73. 地址
  74. </label>
  75. <input
  76. type="text"
  77. {...register('url', { required: true })}
  78. id="url"
  79. className="focus:shadow-outline w-full appearance-none rounded border px-3 py-2 leading-tight shadow focus:outline-none"
  80. required
  81. />
  82. </div>
  83. <div className="mb-4">
  84. <label className="mb-2 block text-sm font-bold " htmlFor="description">
  85. 描述
  86. </label>
  87. <textarea
  88. {...register('description', { required: true })}
  89. id="description"
  90. className="focus:shadow-outline w-full appearance-none rounded border px-3 py-2 leading-tight shadow focus:outline-none"
  91. ></textarea>
  92. </div>
  93. <div className="flex items-center justify-end">
  94. <button
  95. type="submit"
  96. //loading态度
  97. disabled={isLoading}
  98. onClick={handleSubmit(onSubmit)}
  99. className="focus:shadow-outline rounded bg-gray-500 px-4 py-2 font-bold text-white hover:bg-gray-600 focus:outline-none"
  100. >
  101. {isLoading ? <FiCircle /> : '添加'} {/* 根据加载状态切换按钮文本 */}
  102. </button>
  103. </div>
  104. </form>
  105. </div>
  106. </div>
  107. );
  108. async function addLink(newLinkData: AddLinkRequest) {
  109. return await fetch("/api/link/add", {
  110. method: 'POST',
  111. headers: {
  112. 'Content-Type': 'application/json',
  113. },
  114. body: JSON.stringify(newLinkData),
  115. });
  116. }
  117. }

解决

翻阅了无数资料,终于找到了原因!!!https://github.com/orgs/react-hook-form/discussions/8372

根本原因是,表单有err! 所以直接在submit前就被拦截了!

如何检测呢?增加一个函数+一个参数:

  1. const onInvalid = (errors) => console.error(errors)
  2. handleSubmit(onSubmit, onInvalid)

在我的项目里,我终于看到控制台输出错误了···

react-use-form的onSubmit没有被触发 - 图1

原来是参数错了!!

over!