microeinhundert / radonis

Build monolithic applications with a modern, React-based frontend stack based on the Node.js MVC framework AdonisJS.
https://radonis.vercel.app/
MIT License
67 stars 2 forks source link

Programmatically submitting forms - it seems refs are not forwarded to the Form component #12

Closed finestgecko closed 1 year ago

finestgecko commented 1 year ago

I'm trying to protect a signup endpoint with hCaptcha (the invisible type, which appears when the submit button is pressed).

I need to use a ref to programmatically submit the form when the response has been received from hCaptcha.

Here is the code (with some parts redacted for brevity):

function SignupForm({}: SignupFormProps) {
  const [captchaResponse, setCaptchaResponse] = useState<string | null>(null)
  const { formatMessage } = useI18n()
  const formRef = useRef<HTMLFormElement>()
  const captchaRef = useRef<HCaptcha>(null)

  useEffect(() => {
    alert('captchaResponse state changed') // 👈 it reaches here
    if (captchaResponse && formRef?.current) {
      alert('submitting the form...') // 👈 but not here
      formRef.current.submit()
    }
  }, [captchaResponse])

  return (
    <Form
      noValidate
      method="post"
      action="UsersController.create"
      ref={formRef} // 👈 the ref is assigned to the form
      onSubmit={(e) => {
        e.preventDefault()
        if (captchaRef?.current) {
          captchaRef.current.execute() // 👈 this shows the captcha when the submit button is pressed
        }
      }}
    >

         {/* Form goes here */}

          <HCaptcha
            sitekey={process.env.PUBLIC_HCAPTCHA_SITE_KEY!}
            size="invisible"
            onVerify={(token) => setCaptchaResponse(token)}
            ref={captchaRef}
          />
        </div>
      </div>
    </Form>
  )
}

export default hydratable('SignupForm', SignupForm)

And here is the error I get in the console:

Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
Check the render method of `SignupForm`.

The formRef is undefined:

console.log(formRef.current)
undefined

Is there a possible workaround for this?

microeinhundert commented 1 year ago

Since the Form component accepts generics, wrapping it with forwardRef would break that. In your case, it's best to directly use the useForm hook, which is now documented: https://radonis.vercel.app/docs/hooks/use-form

Update to version 2.0.4 to get access to types which were previously not exported.

finestgecko commented 1 year ago

Perfect, thank you!