`useFormAction` needs a way to distinguish between layout and index routes
See original GitHub issueIf you have an action on a parent layout route with a form on the page it works as expected.
When you add an index route to the parent, your code breaks because Remix tries to post to the index route now. This happens because useFormAction returns a URL that matches both routes. When the form is submitted to that URL Remix takes the leaf route, which used to be the parent route but is now the index route.
URL search param?
Maybe there’s a better solution, but I’m thinking useFormAction can append a url search param when it needs to disambiguate. We can keep using the normal URL in all cases except when a parent has an index route.
// useFormAction in the parent route when it has an index route
`/some/where?_routeId=${parentRouteId}`
// when it doesn't have an index route we can keep it clean
"/some/where"
// and the index route, if it has an action, will also be
"/some/where"
Of course, we could be like our loader URLs here and always use the routeIds from the search params, but it would be nice to have clean URLs most of the time since they sometimes end up in the browser URL with <Form forceRefresh>.
But even then that URL is gross, maybe there’s a different way?
Bubbling?
There’s an idea in #195 to go up the route tree to find an action. I’m leery about this, but I dunno, maybe I could be convinced. I don’t think it solves the problem though, because if both the parent and the index have an action, a form in the parent still doesn’t know where to post.
Do nothing, just warn in the compiler?
Over in #195 I was thinking this:
It’s definitely weird that simply adding an index route breaks a previously working form, but the confusion isn’t in the behavior of Remix–that behavior is simple: actions always post to the leaf route–the confusion comes from Remix not telling you that something is wrong with your code when it could have. We should fix that.
We know at build time which routes have actions so we can fail the build if you have a layout route with an action AND an index route at the same time. Annoying you have to move the code, but nice that your app won’t build until you do. Typically lots of code moves to the index route when you refactor like this anyway, so it’s not that big of a deal.
I don’t think that anymore. If I have an action in a route, and I put a <Form method="post"> in the route component, I expect the action in that route to be called, not the index route in some other file. In my task management demo app I’ve got a form in the parent route and I had to move the action to the index route, and now that index route’s action has to handle the actions for the parent and it’s own form (it’s got one too!). It’s not right.
Start making the trailing slash have meaning again?
😬
The way a lot of web servers disambiguate this exact case is the trailing slash.
"/some/where" <-- parent
"/some/where/" < -- index
I think a lot of servers are going to be messing w/ these slashes for “clean URLs” and we’d get into all sorts of trouble with them removing our trailing slash, but I dunno … I kinda love it.
I think right now I’d go with adding the search param in the singular case that a layout route has a form and an index, but I also kinda love the trailing slash idea: it works, the URLs are clean, and it’s old-school.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:5 (4 by maintainers)

Top Related StackOverflow Question
Just realized we could maybe drop the _data param on loaders if we did the trailing slash, too
Ran into a related issue today. If you’re on an index route, the action you get from
useFormActionanduseTransitiondon’t line up.Example: If you have a route
/foo/index.tsxthat looks like thisThen, when you submit the form,
actionForPagewill be/fooandactionBeingSubmittedwill be/foo?index.