【问题标题】:React hook form v7 Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()React hook form v7 函数组件不能被赋予 refs。尝试访问此 ref 将失败。你的意思是使用 React.forwardRef()
【发布时间】:2021-08-24 21:47:12
【问题描述】:

在浏览器中得到错误Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()

我的代码:

import { yupResolver } from '@hookform/resolvers/yup'
import { useState } from 'react'
import { SubmitHandler, useForm } from 'react-hook-form'
import { contactSchema } from 'schemas/schemas'
import { InputFloatLabel } from './components/Inputs/InputFloatLabel'

type TypeFormInput = {
  name: string
  email: string
  textarea: string
}

export const Register = () => {
  const [isLoading, setIsLoading] = useState(false)

  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm<TypeFormInput>({ resolver: yupResolver(contactSchema) })

  const onSubmit: SubmitHandler<TypeFormInput> = async ({ name, email }) => {
    console.log('???? ~ file: Register.tsx ~ line 25 ~ email', email)
    console.log('???? ~ file: Register.tsx ~ line 25 ~ name', name)
  }


  return (
    <div>
      <form onSubmit={handleSubmit(onSubmit)}>
        <div>
          <InputFloatLabel
            type="text"
            placeholder="Name"
            {...register('name')}
          />

          <button type="submit">{isLoading ? 'Loading' : 'Send Mail'}</button>
        </div>
      </form>
    </div>
  )
}

还有输入补偿:

import { useState } from 'react'

type typeInput = {
  placeholder: string
  type?: string
}

export const InputFloatLabel: React.FC<typeInput> = ({ type, placeholder, ...props }) => {
  const [isActive, setIsActive] = useState(false)

  const handleTextChange = (text: string) => {
    if (text !== '') setIsActive(true)
    else setIsActive(false)
  }

  return (
    <div>
      <input
        {...props}
        id={placeholder}
        type={placeholder ? placeholder : 'text'}
        onChange={(e) => handleTextChange(e.target.value)}
      />
      <label htmlFor={placeholder}>
        {placeholder ? placeholder : 'Placeholder'}
      </label>
    </div>
  )
}

我已经构建的 ChakraUI 没有这个问题,但现在只是将普通输入作为一个单独的组件来解决这个问题。

我从这里尝试了一些建议,但仍然无法解决:https://github.com/react-hook-form/react-hook-form/issues/85

【问题讨论】:

标签: reactjs typescript ref


【解决方案1】:

所以问题是我认为{...register("name"}} 行实际上包含一个 ref 属性。您可以 console.log 进行验证;这是我在将{...field} 与 ControlledComponent 一起使用时发现的事实。摆脱控制台错误的一个非常快速的解决方法是,在展开的行之后,添加一个ref={null} 来覆盖从库中传入的这个引用。

【讨论】:

  • 库不需要那个 ref 才能正常工作吗?
【解决方案2】:

您忘记在 InputFloatLabel 中转发 ref。见https://reactjs.org/docs/forwarding-refs.html

你的情况是这样的:

export const InputFloatLabel: React.FC<typeInput> =
    // Use React.forwardRef
    React.forwardRef(({type, placeholder, ...props}, ref) => {
      const [isActive, setIsActive] = useState(false)

      const handleTextChange = (text: string) => {
        if (text !== '') setIsActive(true)
        else setIsActive(false)
      }

      return (
        <div>
          <input
            ref={ref /* Pass ref */}
            {...props}
            id={placeholder}
            type={placeholder ? placeholder : 'text'}
            onChange={(e) => handleTextChange(e.target.value)}
          />
          <label htmlFor={placeholder}>
            {placeholder ? placeholder : 'Placeholder'}
          </label>
        </div>
      )
    })

【讨论】:

    【解决方案3】:

    https://react-hook-form.com/faqs 中,滚动到“如何共享参考使用情况?”有帮助吗?

    import React, { useRef } from "react";
    import { useForm } from "react-hook-form";
    
    export default function App() {
      const { register, handleSubmit } = useForm();
      const firstNameRef = useRef(null);
      const onSubmit = data => console.log(data);
      const { ref, ...rest } = register('firstName');
    
      return (
        <form onSubmit={handleSubmit(onSubmit)}>
          <input {...rest} name="firstName" ref={(e) => {
            ref(e)
            firstNameRef.current = e // you can still assign to ref
          }} />
    
          <button>Submit</button>
        </form>
      );
    }
    

    【讨论】:

      【解决方案4】:

      您的输入组件不会将 ref 导出为 props,因为它是一个函数式组件。

       React.useEffect(() => {
          register('name', { required: true });
        }, []);
      
               <InputFloatLabel
                  type="text"
                  placeholder="Name"
                  name="name"
                 // Remove the register from here
                />
      

      【讨论】:

        猜你喜欢
        • 2020-05-11
        • 2021-12-01
        • 2023-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-03
        • 1970-01-01
        • 2020-11-28
        相关资源
        最近更新 更多