-
Notifications
You must be signed in to change notification settings - Fork 46.7k
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
Bug: Submit events from a button inside a portal don't bubble up to a form in its React DOM Ancestry. #22470
Comments
I've found this bug from 2018 was opened, seemingly with the opposite problem around the same situation, but it was never investigated further as the behavior they experienced is documented as expected: #14456. |
@jviall I think the Dialog Component in material-ui gets destroyed immediately after submitting and hence won't trigger the event-bubbling in form. |
The Either you want to disable the portal or trigger form submission by other means. Support requests filed as GitHub issues often go unanswered. We want you to find the answer you're looking for, so we suggest the following alternatives: Coding Questions https://stackoverflow.com/questions/tagged/react Talk to other React developers |
This directly contradicts what the documentation of Portals describes:
Also, if it is intended that the event shouldn't bubble up to the form outside of the portal, then it shouldn't do so when the second form element is added within the portal. This is contradictory behavior. |
I can validate that this isn't the issue because including the second form element like so
makes bubbling occur as I expect, and the outer form is submitted. |
@eps1lon fwiw, I specifically suggested asking over here when the question came up in Reactiflux, because A) it's a pretty tricky aspect of behavior to begin with, and B) there seems to be some difference between what the docs say should happen and how it's actually behaving. |
Thanks @jviall for responding. I will look into and investigate this issue. |
We're talking about different things. I specificially said "not associated" i.e. the
I think nesting forms (even through a Portal) is another issue (see #20741) since it's technically invalid (if you want the submit to bubble) by HTML spec.
To be clear: This may be expected behavior by you but it's unintended behavior if we respect platform behavior. Nesting forms is not allowed in HTML ("Flow content, but with no form element descendants." -- https://html.spec.whatwg.org/multipage/forms.html#the-form-element). In your example only event bubbling should work since React bubbles event through portals. But the forms itself are completely separate and placement of different fields probably does not work as you think it does. So this issue seems like an unfortunate mix of #20741 and expecting a portaled submitter to be associated with a form that's only the parent in the React tree. I would suggest reducing the issue to just React usage, comparing behavior between 16 and 17 and writing down how exactly you think nesting forms across Portal boundaries should behave (e.g. which submitters are associated with which form, which fields are associated with which forms etc). Note that you can also explicitly associate elements to a form with the |
So the question is if portaling a form-related element outside of a I don't think it's clear that you do want it associated. Let's say we start associating portaled form-related elements with their react-parent What if we start warning? How would people disable this warning if they do intend to de-associate a form-related element with their react-parent Today you already have an API to "re-associate" a portaled form-related element to its react-parrent <div id="portal-container" />
<form id="my-form">
{React.createPortal(<input type="submit" form="my-form" />, document.getElementByID("my-form"))}
</form> What should the API look like to explicitly "de-associate" a form-related element with its react-parent I'm re-opening to get some feedback how React should behave in the scenarios mentioned above. |
This also surprised us in our project. For portaled components, events bubble up the logical hierarchy (React), not the rendered hierarchy (DOM). We expected We'd expect this behavior to be consistent. Our general understanding of portals is "logically this belongs here but in the DOM it should be placed elsewhere". Any related behavior should also be portaled. |
For what it's worth as the original reporter of this issue, I ended up leaning on the Would it be a reasonable compromise to note this behavior somewhere in the documentation of Portals? |
Clear documentation would definitely be helpful. There's more confusing and inconsistent behavior here which is along the same lines. |
My solution import { useState } from "react";
import { createPortal } from "react-dom";
export default function App() {
const [isShowPopup, setIsShowPopup] = useState<boolean>(false);
const onSubmit = (value?: string) => {
console.log(value);
};
return (
<div className="App">
<button onClick={() => setIsShowPopup(true)}>Show Popup</button>
<form
onSubmit={(event) => {
event.preventDefault();
event.stopPropagation();
onSubmit("value1");
}}
>
{isShowPopup &&
createPortal(
<form
onSubmit={(event) => {
event.preventDefault();
event.stopPropagation();
onSubmit("value3");
}}
>
<button type="submit">Submit</button>
</form>,
document.body
)}
</form>
</div>
);
} |
From the docs of React Portal
However this doesn't seem to be the case with
<form>
s when using a<button type='submit'>
that is inside aPortal
.Clicking a submit button that is inside a portal-ed modal which is contained by the
form
does not trigger the form'sonSubmit
event. The only way to get it to do so, is to wrap the submit button in an additional<form>
element that is inside the portal as well. When this is done, then event bubbles up to both forms, and the original, outer form'sonSubmit
is triggered as desired.React version: 16.14.0
Steps To Reproduce
Portal
, such as a modal.Portal
, add a submit button, e.g.<button type='submit'>submit</button>
.Workaround
Portal
, wrap the submit button you've made in an additionalform
element.Link to code example: https://codesandbox.io/s/new-dust-b6hoh?file=/src/App.tsx
The current behavior
Clicking the button inside the portal does not result in the form being submitted.
Clicking the button inside the portal with an additional form element results in both forms being submitted.
The expected behavior
The form outside of the portal is submitted by the portal's submit button (without including any additional form elements).
The text was updated successfully, but these errors were encountered: