Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fetcher with {...getFormProps(form)} causes a navigation to the action #444

Closed
jmaldon1 opened this issue Feb 12, 2024 · 11 comments
Closed

Comments

@jmaldon1
Copy link

Describe the bug and the expected behavior

When you submit a fetcher when using {...getFormProps(form)} it will navigate to the action route. Based on remix docs a Fetcher shouldn't cause a navigation https://remix.run/docs/en/main/hooks/use-fetcher#fetcherform

Conform version

v1.0.1

Steps to Reproduce the Bug or Issue

function SomeComponent() {
  const fetcher = useFetcher();
  const [form] = useForm<Schema>({});


  return (
    <fetcher.Form method="post" action="/some/route" {...getFormProps(form)}>
      <input type="text" />
    </fetcher.Form>
  );
}

When submitting this fetcher, it causes the browser to navigate to /some/route

What browsers are you seeing the problem on?

Chrome

Screenshots or Videos

No response

Additional context

No response

@edmundhung
Copy link
Owner

Conform is only calling event.preventDefault() for you when validation failed so it's up to the Form component to decide what happened when the submit event is not default prevented.

When submitting this fetcher, it causes the browser to navigate to /some/route

Keep in mind this is true only if you are running with JS. When you submit a form before JS loaded, it will still be a navigation due to how browser works with the form element. Also, if you redirect in the action, it will still cause a navigation.

I will suggest you to remove the {...getFormProps(form)} to verify the behaviour.

@jmaldon1
Copy link
Author

Got it, so is the solution to not add the {...getFormProps(form)} to the fetcher to prevent this behavior? I just assumed we wanted those props on all of our forms.

@edmundhung
Copy link
Owner

No. I am just suggesting this is very likely a Remix behaviour and you will observe the same behaviour even without {...getFormProps(form)}

@jmaldon1
Copy link
Author

jmaldon1 commented Feb 12, 2024

So just to clear things up and to just let you know what I am seeing (JS loaded in both examples)

  1. When I submit the fetcher with {...getFormProps(form)} it redirects me to /some/route
  2. When I submit the fetcher without {...getFormProps(form)} it does NOT redirect me to /some/route

So I think you are saying that I should add code to prevent a redirect even if remix handles it automatically with JS because if JS is not loaded it would redirect me?

@edmundhung
Copy link
Owner

It will be great if you can create a repo with the issue you had. You can use the example here: https://stackblitz.com/github/edmundhung/conform/tree/main/examples/remix?file=app%2Froutes%2Flogin-fetcher.tsx

Conform does nothing in addition to event.preventDefault(), so I have no idea how it could impact the remix behaviour at the moment. A repo will help me understand it better. Thanks!

@jmaldon1
Copy link
Author

jmaldon1 commented Feb 12, 2024

This is the best I was able to repro. In this repro case it only breaks when I do add the onSubmit (somehow in the repro case it works fine with {...getFormProps(form)}), however on my app it even breaks when I add {...getFormProps(form)}.

https://stackblitz.com/edit/github-kv6hgp?file=app%2Froutes%2Flogin-fetcher.tsx

Click With Fetcher link and then click the SUBMIT WITH ACTION button under the login button.

@edmundhung
Copy link
Owner

The issue your repo has is caused by missing form id. It will work correctly if you add the form id like this:

<fetcherWithAction.Form
      method="POST"
      action="/some-action"
      id={formWithAction.id}
      onSubmit={formWithAction.onSubmit}
/>

This is probably not the exact issue you had as the getFormProps() helper will always return an id. But there might be an error thrown in the submit handler that cause Remix falling back to full page reload. Maybe try wrapping the onSubmit handler in a try-catch block and see if you notice something strange there:

<fetcherWithAction.Form
      method="POST"
      action="/some-action"
      id={formWithAction.id}
      onSubmit={event => {
        try {
          formWithAction.onSubmit(event);
        } catch (exception) {
           console.log(exception);
        }
      }}
/>

You can also wrap the onValidate option in a try-catch block and see if it throws an exception. I have heard people having issue because the zod schema is not available in the client bundle so client validation failed 😅

@jmaldon1
Copy link
Author

jmaldon1 commented Feb 12, 2024

Oh interesting, my issue is caused by this: #375

This is the exception being thrown from the onSubmit:

Error: The submit event is dispatched by form#:Rd6l36H7: instead of form#:R39l8pH7:

I also see this error in my console when i reload the page:

Prop `id` did not match. Server: ":Rd6l36H7:" Client: ":R39l8pH7:"

The fixes in #375 haven't worked for me. I am on remix v2.6 and conform v1.0.1.

But its interesting that the repro case isn't having this issue. Must be something wrong with my app, but I haven't been able to narrow down why its happening.

@jmaldon1
Copy link
Author

jmaldon1 commented Feb 12, 2024

Ok so I have an app that uses MUI and the set up is very similiar to this https://github.com/mui/material-ui/tree/master/examples/material-ui-remix-ts) in the entry.client and entry.server files. I have a mismatch there which is causing issuing with the form IDs when using conform.

Seems like this is a me issue that I'll need to figure out. Going to close.

@edmundhung
Copy link
Owner

edmundhung commented Feb 14, 2024

In case you have trouble fixing the mismatch in a short time, you can consider hard-coding the id of the form for now, e.g.

const [form, fields] = useForm({
  id: 'example',
});

Just be aware that the id has to be unique if you might render multiple forms at the same time. And the issue is likely happening on other non fetcher form but feels working due to how resilient Remix + Conform is 😅

@jmaldon1
Copy link
Author

jmaldon1 commented Feb 15, 2024

Something interesting I found is that even with the fix I made, I will still get the error The submit event is dispatched by form#:r0: instead of form#:r0:, if I have 2 <Form>s on a page that both use the same useForm and {...getFormProps(form)}.

Which I guess makes sense since they'll have the same ID but just something I didn't know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants