React JSON Schema Form提交后如何自动聚焦首个校验错误的表单字段
React JSON Schema Form 提交后自动聚焦首个校验失败字段实现方案
以下是三种可直接落地的实现思路,可根据你的项目复杂度选择:
方案1:使用内置
onError回调+DOM选择器(轻量场景首选)
rjsf的Form组件原生提供onError回调,提交校验失败时会触发,回调第一个入参为全量错误数组,默认返回的错误顺序和Schema定义的字段顺序完全一致。
你可以直接取数组的第一个错误项,通过其property字段拿到对应字段的路径,将路径格式转换为rjsf默认生成的表单元素name属性规则(路径前缀/替换为root_,路径内的/替换为_,比如/username对应root_username),之后直接通过DOM选择器匹配元素调用focus()即可,示例逻辑如下:const handleFormError = (errors) => { if (!errors.length) return const firstErrorPath = errors[0].property // 转换为name属性对应值 const fieldName = firstErrorPath.replace(/^\//, 'root_').replaceAll('/', '_') // 匹配第一个可输入元素聚焦 const targetEl = document.querySelector(`[name="${fieldName}"]`) targetEl?.scrollIntoView({ behavior: 'smooth', block: 'center' }) targetEl?.focus() }方案2:自定义字段组件绑定ref(稳定场景首选)
如果你项目有自定义字段组件的需求,可在封装字段时统一存储所有字段的路径和对应DOM引用,在校验失败时直接通过引用聚焦,不受DOM结构变化影响:import { useRef, useEffect } from 'react' import Form from "@rjsf/core" import validator from "@rjsf/validator-ajv8" const MyForm = () => { // 全局存储所有字段的ref映射 const fieldRefs = useRef({}) // 封装自定义字段组件 const WrapField = (FieldComponent) => (props) => { const fieldRef = useRef(null) // 挂载时存储路径和ref的映射 useEffect(() => { fieldRefs.current[props.id] = fieldRef return () => delete fieldRefs.current[props.id] }, [props.id]) return <div ref={fieldRef}><FieldComponent {...props} /></div> } // 校验失败回调 const handleError = (errors) => { if (!errors.length) return const firstErrorId = errors[0].id fieldRefs.current[firstErrorId]?.current?.scrollIntoView({ behavior: 'smooth' }) fieldRefs.current[firstErrorId]?.current?.querySelector('input,select,textarea')?.focus() } return ( <Form schema={yourFormSchema} validator={validator} onError={handleError} fields={{ StringField: WrapField(Form.defaultProps.fields.StringField), NumberField: WrapField(Form.defaultProps.fields.NumberField), BooleanField: WrapField(Form.defaultProps.fields.BooleanField) }} /> ) }方案3:结合
transformErrors自定义聚焦优先级
如果你需要调整聚焦的优先级(比如优先聚焦必填项错误,再聚焦格式错误),可以搭配Form组件的transformErrors属性,先对错误数组按自定义规则排序,之后onError回调中拿到的第一个错误就是你需要优先聚焦的字段。
注意:如果你使用的是rjsf的UI库适配版本(比如Ant Design、MUI适配包),自定义字段时需要对应替换适配包提供的默认字段组件,ref绑定位置需要对准实际的输入元素避免聚焦失效。
内容的提问来源于stack exchange,提问作者Stefan Deak
相关产品推荐
相关产品推荐

