You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何捕获RJSF(react-jsonschema-form)的HTML5表单校验错误?

实现方案

前置原因说明

RJSF内置的validate、transformErrors回调仅在浏览器原生HTML5校验通过后才会执行。HTML5校验属于浏览器层面的提交拦截逻辑,不会进入RJSF自身的业务校验流程,因此这两个回调无法捕获HTML5校验错误是正常表现。
你在控制台看到的An invalid form control with name='' is not focusable属于浏览器内部输出的校验警告,并非JS运行时抛出的可捕获异常,常规try/catch、全局异常监听都无法拿到这类信息,不需要在异常捕获方向耗费精力。

核心实现:监听原生invalid事件

HTML5校验失败时,浏览器会在对应未通过校验的表单元素上触发invalid事件。直接在表单根元素上绑定捕获阶段的事件监听器,即可拿到所有校验失败的字段引用,同步执行手风琴展开逻辑,全程不需要关闭HTML5校验特性,也不影响原有业务逻辑。

注意:invalid事件天然不支持冒泡,必须在事件捕获阶段绑定监听器才能正常触发。

参考实现代码

import { useRef, useEffect } from 'react';
import Form from '@rjsf/core';

export default function DynamicForm() {
  const formRef = useRef(null);
  const submitRef = useRef(null);
  // 原有表单状态、手风琴展开状态等逻辑保留
  // const [formData, setFormData] = useState({})
  // const [openAccordionKeys, setOpenAccordionKeys] = useState([])

  useEffect(() => {
    // RJSF的ref实例上直接挂载了原生form DOM元素引用
    const nativeForm = formRef.current?.formElement;
    if (!nativeForm) return;

    const handleInvalidField = (e) => {
      // 若不需要浏览器默认的错误提示浮层,可放开下一行代码
      // e.preventDefault();

      // 拿到当前校验失败的表单DOM元素
      const invalidField = e.target;

      // 手风琴展开逻辑,可根据自身使用的组件库调整:
      // 1. 非受控手风琴场景(如原生Bootstrap手风琴):向上查找父级面板,模拟点击展开
      const accordionItem = invalidField.closest('.accordion-item');
      if (accordionItem) {
        const collapsedBtn = accordionItem.querySelector('.accordion-button.collapsed');
        collapsedBtn?.click();
      }

      // 2. 受控手风琴场景(如Antd、React-Bootstrap受控模式):拿到面板key后更新展开状态
      // const panelEl = invalidField.closest('[data-accordion-key]');
      // if (panelEl) {
      //   const currentKey = panelEl.dataset.accordionKey;
      //   setOpenAccordionKeys(prev => Array.from(new Set([...prev, currentKey])));
      // }
    };

    // 绑定捕获阶段的事件监听,第三个参数必须传true
    nativeForm.addEventListener('invalid', handleInvalidField, true);

    return () => {
      nativeForm.removeEventListener('invalid', handleInvalidField, true);
    };
  }, []);

  return (
    <Form
      ref={formRef}
      formData={formData}
      // 原有validate、transformErrors等配置全部保留,无需修改
    >
      <button className="hidden" ref={submitRef} />
    </Form>
  );
}

注意事项

  • 该方案完全兼容现有编程式提交逻辑,无论用户手动点击提交,还是上层代码调用submitRef?.click()触发提交,HTML5校验触发时都会正常执行绑定的处理逻辑。
  • 只要在校验失败的第一时间展开对应面板,之前遇到的「失效表单控件无法聚焦」的控制台警告会自动消失——元素展开后浏览器可以正常定位并聚焦到错误字段。
  • 绑定在表单根元素上的捕获阶段监听器,会自动响应后续动态渲染的新增字段,不需要因为表单字段动态变化重复绑定事件。
  • 不要尝试通过JS异常捕获的方式获取浏览器控制台的校验警告,这类警告是浏览器内部校验流程直接打印的,不会进入JS异常队列,所有异常捕获API都无法拿到相关信息。

内容的提问来源于stack exchange,提问作者Michal Kurz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 20:06:26