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

Native event.stopPropagation outside of React root cuts out React events #8693

Closed
hejtmii opened this issue Jan 5, 2017 · 5 comments
Closed

Comments

@hejtmii
Copy link

hejtmii commented Jan 5, 2017

We need to host a standalone React component (DraftJS editor) inside a HTML5 application which will run on other JS framework, or even plain JS or jQuery.
The code of the application is beyond our control, we are just a vendor of a component which adds some content, part of which is this React-based editor.

Anyway, the most important part is that we need to add the component with the following code to an existing DIV.

const editor = ReactDOM.render(
    React.createElement(
      EditorComponent,
      props
    ),
    divElem
  );

EditorComponent is a regular React component with some onClick events attached to its content (primarily toolbar buttons for the editor).

I learned that React event model and its bubbling executes independently after the event bubbles all the way up to the document, and that if ev.stopPropagation() is called on native event, React events won't execute at all.
That is understandable for situations where document contains only the React app / component at its root and no other content, meaning you have control over all events on the page from React code.

However, when React component is just a small fraction of the entire page, it may be severely influenced by the rest of the page.
The problem is that any event handling code above the component which calls ev.stopPropagation() cuts of the events of that smaller fraction, even that the event originated from the React component scope.
That influencing code could very well be just some jQuery plugin, so even author of the page may not be able to rewrite their code for some special event handling.

Here is a fiddle to demonstrate that: https://jsfiddle.net/martinh_kentico/kept9anh/3/

I believe that the point where the event chain breaks, allowing React to execute its events, should be the root element of React component, rather than the whole document.
This way, React root element could be considered an isolation edge of the React application / component.

reactevents

I tracked the React event registration down to function ReactDOMComponent.ensureListeningTo(...) where I found the following code:

  var doc = isDocumentFragment ? containerInfo._node : containerInfo._ownerDocument;
  listenTo(registrationName, doc);

I tried to change containerInfo._ownerDocument to containerInfo._node to register the React event chain to the root of the React container, and tried it for several basic events (onClick, onMouseDown/Up) and it seems working for us as expected.
React events are not influenced by stopping propagation at the native events outside of React component root, so the two differently implemented parts of the application can coexist in peace.

I am not sure why _ownerDocument was chosen over _node in the implementation and if changing it to _node could break something important.

Please advise if the proposed solution seems viable (in that case consider a change to that), or for what reasons you wouldn't recommend it.

@aweary
Copy link
Contributor

aweary commented Jan 6, 2017

@kenticomartinh thanks for the well thought out and detailed issue! This is something that's been requested a number of times in the past, see #7088 #2043.

#7088 is an open PR that implements essentially the same solution that you've proposed, you can read the comments there for some context on why this hasn't been done yet.

@hejtmii
Copy link
Author

hejtmii commented Jan 6, 2017

Thank you! I couldn't find them, probably because I was searching by problem keywords, not solution keywords :-) I willl observe them.

If I understand it correctly, if we use only some basic events e.g. onClick in our small React components, and support latest enough versions of browsers, the temporary fix should be pretty safe. Or is there some set of DOM events that React listens to that are attached automatically regardless of whether we register them or not?

@gaearon
Copy link
Collaborator

gaearon commented Oct 4, 2017

I’ll close as a duplicate of #2043.

@gaearon
Copy link
Collaborator

gaearon commented Aug 10, 2020

We're changing this in React 17 to attach to roots.

@gaearon
Copy link
Collaborator

gaearon commented Aug 11, 2020

If you want to try it, we released 17 RC yesterday with this change:
https://reactjs.org/blog/2020/08/10/react-v17-rc.html

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

No branches or pull requests

3 participants