seasonedcc / remix-forms

The full-stack form library for Remix and React Router
https://remix-forms.seasoned.cc
MIT License
490 stars 25 forks source link

Can't trigger onSubmit from Form-component #230

Open sndrem opened 11 months ago

sndrem commented 11 months ago

I can't seem to trigger a handleSubmit function when using custom components.

Expected behaviour I would expect to see Hello World printed in the console.

Nothing seems to happen when submitting.

I have provided a small codesandbox here https://codesandbox.io/p/sandbox/bold-wind-pgnvq9?file=%2Fapp%2Froutes%2Findex.tsx%3A28%2C21

Am I doing something wrong, or missing something? I have read the change log and all the examples, but I can't seem to understand how to call the handleSubmit function.

I have tried to use the submit function, but if used, then the action is called twice.

My use case is to do some async data operations before submitting the form.

I am on the latest version om Remix and remix-forms, as well as zod, domain-functions and react-hook-forms.

danielweinmann commented 11 months ago

Hey, @sndrem!

First, it is weird that your custom onSubmit is only being called when there are no children to Form. I tested it in the sandbox and was able to reproduce it. I couldn't understand why just by reading the code. The desired behavior is for you to have control over onSubmit regardless of whether you pass children or not.

That said, I don't recommend customizing onSubmit unless you really need it. In your example, you're losing the client-side validations from react-hook-form and would have to reimplement it manually.

About using the submit function, it is intended to be used for triggering manual submits, not reacting to user submits.

Can you tell us more about your specific use case so we can try to help find the right API to use?

I'll keep this issue open until we fix the bug that doesn't allow custom onSubmit when the form has children.

sndrem commented 11 months ago

Sure @danielweinmann

My use case is that I need to fetch a token from Googles Recaptcha before submitting the form.

const handleSubmit = async (event: FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    // I need to fetch a token from the executeRecaptcha function just before submitting the form
    const token = await executeRecaptcha?.();
    if (token) {
      const formData = new FormData(event.target as HTMLFormElement);
      // I need to add the token to the formdata so that I can access it in the action and then do a fetch call to Google to verify 
      // if the submitter is a human or a bot
      formData.set("token", token);
      submit(formData, { method: "post", encType: "multipart/form-data" });
    }
  };

I am not sure how to do this other wise. It has worked fine for the past year, but when upgrading now, it fails.

I might be able to execute the executeRecaptcha function in a useEffect and it to a hidden form field right away, but I have not tried that yet. Not sure if the token lasts long enough if the user navigates to the form, then waits a long enough time before submitting.

gustavoguichard commented 11 months ago

@sndrem , by looking at your code sample I wonder if you could be executing the recaptcha in the background and adding its token to a hidden input in the form instead of customizing the onSubmit? Going even further: can't you load the token in a loader and have it ready by the time the form is mounted?

sndrem commented 11 months ago

@gustavoguichard I will try to implement your ideas of either fetching the token in the background or as a part of the loader to the page.

I'll update this issue with my findings.

sndrem commented 11 months ago

Since the function to fetch the token comes from a hook I decided to add a useEffect which updates a hidden field in the form. That works fine for me.

This issue can be closed from my side.

gustavoguichard commented 10 months ago

@sndrem I'm glad it worked for you :)