KotlinJS接入react-hook-form如何正确绑定表单元素并触发提交验证
KotlinJS通过Dukat封装层适配react-hook-form的绑定问题
我尝试通过Dukat和封装层(Wrappers)让react-hook-form适配KotlinJS运行,目前的实现与遇到的问题如下:
封装层本身运行正常,我在控制台打印确认,调用的确实是库原生的
useForm方法
最初的实现代码
我是如下方式使用useForm钩子的:
val useForm = useForm<ProfileModel>() val register = useForm.register val errors = useForm.formState.errors val handleSubmit = useForm.handleSubmit val registerInstagram = register("instagram", object : validateOptions<ProfileModel, Any> { override var required = true override var maxLength = 40 }) form(classes = "") { attrs.onSubmit = { it.preventDefault() console.log("Submit") handleSubmit({ data, ev -> console.log("On Submit " + data) }, { errors, ev -> console.log("On submit error " + errors) }) } input(type = InputType.text, classes = "$defaultInputStyle mb-4") { attrs.placeholder = "Name" register("name", object : validateOptions<ProfileModel, Any> { override var required = true override var maxLength = 15 }) } input(type = InputType.text, classes = "$defaultInputStyle mb-4") { this.ref = registerInstagram.ref attrs { this.placeholder = "Instagram" this.onChange = registerInstagram.onChange this.onBlur = registerInstagram.onBlur this.name = registerInstagram.name } } button(classes = defaultButtonStyle, type = ButtonType.submit) { +"Submit" } }
useForm本身运行正常,可以正确返回register、errors等所需属性,但无法与KotlinJS中的Input元素正确绑定。
register方法的返回值接口已做适配,符合React DOM的属性要求。常规React开发中使用<Input {...register}即可自动将返回的四个属性绑定到元素上,我定义的返回值接口如下:
external interface UseFormRegisterReturn { var onChange: ChangeEventHandler<*> // I changed this var onBlur: FocusEventHandler<*> // I changed this var ref: RefCallback<*> //I changed this var name: InternalFieldName }
但点击提交按钮时,仅会打印"Submit"日志,useForm的handleSubmit方法没有执行,也没有任何数据输出,不清楚这套配置还存在什么缺失。
封装层其余相关代码
@JsName("useForm") external fun <TFieldValues : FieldValues> useForm(props: `T$23`<TFieldValues> = definedExternally): UseFormReturn<TFieldValues, Any> external interface UseFormReturn<TFieldValues : FieldValues, TContext : Any?> { var watch: UseFormWatch<TFieldValues> var getValues: UseFormGetValues<TFieldValues> var setError: UseFormSetError<TFieldValues> var clearErrors: UseFormClearErrors<TFieldValues> var setValue: UseFormSetValue<TFieldValues> var trigger: UseFormTrigger<TFieldValues> var formState: FormState<TFieldValues> var reset: UseFormReset<TFieldValues> var handleSubmit: UseFormHandleSubmit<TFieldValues> var unregister: UseFormUnregister<TFieldValues> var control: Control<TFieldValues, TContext> var register: UseFormRegister<TFieldValues> var setFocus: UseFormSetFocus<TFieldValues> }
核心问题
我该如何将useForm的register方法正确绑定到我的表单元素上?
问题更新补充
我已经调整了部分配置,需要修改的点如下:
div("w-screen h-screen items-center justify-center p-4") { form(classes = "") { attrs.onSubmit = { it.preventDefault() // 1) handleSubmit({ data, ev -> console.log("On Submit ", data) }, { errors, ev -> console.log("On submit error ", errors) })(it) // 2) } input(type = InputType.text, classes = "$defaultInputStyle mb-4") { this.ref = registerInstagram.ref attrs { // 3) this.placeholder = "Instagram" this.onChange = registerInstagram.onChange this.onBlur = registerInstagram.onBlur this.name = registerInstagram.name } } button(classes = defaultButtonStyle, type = ButtonType.submit) { +"Submit" } } }
修改点说明:
- 阻止表单默认提交事件(如果不需要页面刷新)
- handleSubmit方法本身会返回一个需要传入事件参数的函数,我原来漏了调用这个返回的函数,需要写成
handleSubmit()()的形式 - 完整绑定register返回的所有属性:onBlur、name、onChange和ref
调整后已经可以正常提交数据,但表单验证和错误提示功能仍然未生效。
解决方案
提交逻辑修复
你之前的核心提交问题已经通过修正handleSubmit的调用方式解决:react-hook-form的handleSubmit是高阶函数,接收成功/失败回调后返回实际的事件处理函数,必须主动传入表单事件触发执行,不能直接把它赋值给onSubmit就结束。
表单验证不生效修复
- 检查所有带校验规则的字段绑定完整性:你代码里的
name字段调用了register但是没有把返回的onChange/onBlur/ref/name绑定到对应input上,相当于这个字段完全没有被注册到react-hook-form的状态管理里,自然不会触发验证。所有字段都要和Instagram字段一样,完整绑定register返回的四个属性。 - 适配formState响应性:KotlinJS的React封装对外部JS库的响应式对象监听可能存在适配问题,调用
useForm时可以显式传入mode参数指定验证触发时机(比如mode = "onBlur"或者mode = "onChange"),同时确保你读取errors的逻辑是在React的重渲染流程里,或者用watch主动监听formState的变化触发UI更新。 - 对齐验证规则接口:检查你定义的
validateOptions接口是否和react-hook-form原生的校验参数完全对齐,有没有遗漏message等属性,或者字段名拼写错误导致校验规则没有被正确传入原生方法。 - 修正ref泛型:你定义的
UseFormRegisterReturn里的RefCallback不要用*通配符,明确指定为HTMLInputElement,避免ref绑定失败导致react-hook-form无法获取到表单元素的实例,进而无法触发校验。
内容的提问来源于stack exchange,提问作者Nikola-Milovic
相关产品推荐
相关产品推荐

