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

使用react-hook-form的Controller组件时触发无效Hook调用错误

React Hook Form Controller 数字输入触发 Invalid Hook Call 错误的解决办法

作为react-hook-form新手,我原本想让Controller组件处理数字类型的输入值,参考相关方案修改代码后,却触发了Invalid Hook Call错误,以下是我的代码和排查思路:

问题背景

最初发现Controller无法直接以数字类型处理输入值,参考方案修改了onChange逻辑:

<Controller
  // 去掉了rules里的valueAsNumber: true
  render={({ field }) => (
    <input
      type="number"
      onChange={(event) => field.onChange(+event.target.value)} // 手动转数字
    />
  )}
/>

基于这个思路封装了NumberInput组件,但运行后报错Invalid Hook Call:

import React, { ChangeEvent } from 'react'
import { Controller } from 'react-hook-form'
import { getPlaceholder } from './getPlaceholder'
import { IInput } from './types'

const NumberInput: React.FC<IInput> = ({ control, name, ...props }) => {
  const placeholder = getPlaceholder({ type: "number" });
  const numericalOnChange = (event: ChangeEvent<HTMLInputElement>) => {
    if (event.target.value === '') return null;
    return +event.target.value;
  }

  return (
    <Controller
      control={control}
      name={name}
      render={({ field: { onChange, ...field } }) => (
        <input
          {...props}
          {...field}
          type="number"
          placeholder={placeholder}
          onChange={(event) => {
            const value = numericalOnChange(event)
            onChange(value)
          }}
          className="h-[20px] pl-[4px] py-[8px] bg-transparent border-b
          border-b-[#646464] focus:border-b-[#3898EC] text-[13px]
          text-[#F00] placeholder-[#646464] outline-none m-1 w-full"
        />
      )}
    />
  )
}

export default NumberInput

错误原因排查与解决

Invalid Hook Call错误通常是违反了React Hooks的使用规则,结合代码来看,最可能的问题点:

1. 检查getPlaceholder函数是否调用了React Hooks

如果getPlaceholder内部使用了useState、useEffect等Hook,但它本身不是自定义Hook(没有以use开头命名),也不是在React组件/自定义Hook的顶层调用,就会触发这个错误。

解决办法:
如果getPlaceholder依赖Hook逻辑,将其改为自定义Hook,遵循命名规则:

// 修改getPlaceholder为自定义Hook
export function useGetPlaceholder(params: { type: string }) {
  // 原来的逻辑(如果有Hook调用,比如useState)
  // const [placeholder] = useState(...)
  // ...
  return placeholder;
}

// 在NumberInput中调用
const NumberInput: React.FC<IInput> = ({ control, name, ...props }) => {
  const placeholder = useGetPlaceholder({ type: "number" }); // 组件顶层调用自定义Hook
  // ... 其余代码不变
}

2. 确认父组件中control的传递是否正确

确保父组件里的control是通过useForm()正确获取的,且传递给NumberInput时没有错误:

import { useForm } from 'react-hook-form';
import NumberInput from './NumberInput';

function ParentComponent() {
  const { control } = useForm({
    defaultValues: {
      // 确保默认值类型匹配,比如数字或null
      age: null
    }
  });
  return <NumberInput control={control} name="age" />;
}

3. 可选:简化onChange逻辑

可以去掉单独的numericalOnChange函数,直接内联处理,让代码更简洁:

onChange={(event) => {
  const inputValue = event.target.value;
  onChange(inputValue === '' ? null : +inputValue);
}}

内容的提问来源于stack exchange,提问作者Noah -

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 23:15:32