forge42dev / remix-hook-form

Open source wrapper for react-hook-form aimed at Remix.run
MIT License
354 stars 29 forks source link

Submit error if used with formData() method #11

Closed kurdin closed 1 year ago

kurdin commented 1 year ago

Hello, I have a simple input that is not part of the validation form <input type="hidden" name="redirectTo" value={redirectTo} />

I want to get this input value in the action function along with getValidatedFormData method, but using await request.formData() together with await getValidatedFormData<FormData>(request, resolver) throw backend error

TypeError: body used already for: http://localhost:3000/login

You can replicate this issue by adding a simple input field into the form and try to get its value on submit the form in the action method using formData method.

AlemTuzlak commented 1 year ago

Hi @kurdin The issue you are facing is due to the fact that the getValidatedFormData consumes the requests body and you can only read the body once. You have two options here, either set the redirectTo into the defaultValues in the useRemixForm hook that will allow you to get it directly from getValidatedFormData, or you can use await request.formData() and then use another method called validateFormData to validate it, you can find it in the docs of this package.

kurdin commented 1 year ago

@AlemTuzlak I missed validateFormData, this would work. Thank you for your time to create this lib and your explanation.

AlemTuzlak commented 1 year ago

No problem, thank you for the support and kind words, code on!

kurdin commented 1 year ago

@AlemTuzlak sorry for reopening but if I use handleSubmit from useRemixForm <Form method="post" onSubmit={handleSubmit}> in action method I don't have anything in formData object.


export async function action({ request }: ActionArgs) {
    const formData = await request.formData();

    const remember = formData.get('remember');
    const redirectTo = formData.get('redirectTo')?.toString() || '/messages';

    console.log('redirectTo', redirectTo);
    console.log('remember', remember);

    const { errors, data } = await validateFormData<FormData>(formData, resolver);

    if (errors) {
        return json(errors);
    }

    const { password, email } = data;
    ...
}

validateFormData always returns an error because it could not find password or email in formData.

Do I need to do anything special in handleSubmit or in onValid with help of createFormData ?
Or better just not to mix formData with remix-hook-form data ?

Thank you again for your help, trying to wrap around my head over remix framework and evaluate it for my next app.

kurdin commented 1 year ago

I was trying to use getValidatedFormData but issue I see is that anything I return from the action become errors inside frontend component

is there a way to return data but not a errors ?

export async function action({ request }: ActionArgs) {
    const { errors, data } = await getValidatedFormData<FormData>(request, resolver);

    if (errors) {
        return json(errors);
    }

    return json(data);
}
kurdin commented 1 year ago

@AlemTuzlak Thank you again for all your help but I decided to go with vite/vite-plugin-ssr instead of remix. You can develop with vite-plugin-ssr just like in regular react and also can have ssr if you need for some routes. This is a perfect combination for my needs.

AlemTuzlak commented 1 year ago

@kurdin the reason behind this is that the formData that is submitted via the hook is all placed into an object and sent to the be via formData, so if you did

const formData = await request.formData();
const data = formData.get("formData")

you would've gotten the whole object and could've done whatever you wanted with it!