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

React Native中React Hook Form父子组件传值与表单异常排查

问题修复方案

你的问题是几处语法和API使用错误叠加导致的,和父子组件传值逻辑、传form实例/useFormContext的方案本身无关:

  • 提交事件绑定完全错误:
    1. 你写的handleSubmit(onSubmit())会在组件渲染阶段立刻执行onSubmit,此时还没触发提交流程,拿到的data自然是undefined,正确写法是传入函数引用handleSubmit(onSubmit),不要加括号调用。
    2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 06:27:14