React Native中React Hook Form父子组件传值与表单异常排查
问题修复方案
你的问题是几处语法和API使用错误叠加导致的,和父子组件传值逻辑、传form实例/useFormContext的方案本身无关:
- 提交事件绑定完全错误:
- 你写的
handleSubmit(onSubmit())会在组件渲染阶段立刻执行onSubmit,此时还没触发提交流程,拿到的data自然是undefined,正确写法是传入函数引用handleSubmit(onSubmit),不要加括号调用。 - React Native的Button组件触发回调的属性是
onPress,不是web端的onSubmit,你原来绑定的onSubmit属性在RN Button上根本不会被触发,这也是你改成正确的handleSubmit写法后看不到任何日志的直接原因。
- 你写的
- 子组件Controller的解构语法错误,还存在拼写错误:
你写的render={({ field: onBlue, onChange, value }) =>有两个问题:一是onChange/value/onBlur都是field对象的内部属性,你少写了一层解构大括号,这种写法是把整个field对象赋值给名为onBlue的变量,根本拿不到实际的绑定方法;二是把onBlur错拼成了onBlue。这两个问题导致输入框的值变更完全没有同步到表单实例。 - 父组件return的JSX没有根容器:React Native要求组件返回的多个同级节点必须包裹在View/Fragment这类根容器下,你原来直接并列返回WaterStep和Button会直接报渲染错误,阻断代码执行。
React Native下是否必须使用control
是,RN场景下必须通过Controller或者useController配合control做字段绑定,不能直接用web端的register方法。register依赖Web DOM的ref、原生input事件机制,RN的TextInput等输入组件没有对应的DOM实现,不支持register的绑定逻辑,官方文档只展示control的用法就是这个原因。
修正后的可运行代码
父组件
import { View, Button } from 'react-native'; import { useForm, useWatch } from 'react-hook-form'; const Stepper = () => { const form = useForm({ defaultValues: { testResult: "", } }); const { control, handleSubmit, formState: { errors } } = form; const testResult = useWatch({ control, name: "testResult" }); const onSubmit = (data) => { console.log("watched testResult value: ", testResult); console.log("form submission data: ", data); }; return ( <View> <WaterStep form={form} /> <Button title="提交" onPress={handleSubmit(onSubmit)} /> </View> ) }
子组件
import { TextInput } from 'react-native'; import { Controller } from 'react-hook-form'; const WaterStep = ({ form }) => { const { control, formState: { errors } } = form; return ( <Controller name="testResult" control={control} rules={{ maxLength: 3, required: true, }} render={({ field: { onBlur, onChange, value } }) => ( <TextInput keyboardType="number-pad" maxLength={3} onBlur={onBlur} onChangeText={onChange} value={value} style={{ borderWidth: 1, borderColor: '#eee', padding: 10 }} /> )} /> )}
如果你的表单有15个字段拆分在多个子组件里,更推荐用FormProvider+useFormContext的方案:父组件用FormProvider包裹子组件传入form实例,子组件不需要逐层接收form props,直接调用useFormContext()就能拿到control等表单方法,维护起来更简洁。
内容的提问来源于stack exchange,提问作者djangodev
相关产品推荐
相关产品推荐

