Bug: The onChange synthesis event is not propagation when the child node is added through dangerouslySetInnerHTML
iwfan opened this issue · comments
The onChange synthesis event is not propagation when the child node is added through dangerouslySetInnerHTML.
React version: v17.0.2
Link to code example:
https://codesandbox.io/s/restless-rain-otyzx?file=/src/App.js
Steps To Reproduce
- click the radio input element
- see logging in console
The current behavior
- ✅ onClick event is propagation
- ❌ onChange event is not propagation
The expected behavior
- onClick event is propagation
- onChange event is propagation
@iwfan You added onChange event listener (onChange={handleSyntheticChangeEvent}
) to the <div>
element.
Read more about change
event: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/change_event.
The change event is fired for
<input>
,<select>
, and<textarea>
.
I don't think it works for divs.
Hi @cyntler, I know that change event are triggered for <input>
, <select>
, and <textarea>
, but the change event can be propagated through bubbles.
<div
onChange={handleSyntheticChangeEvent} // It's not working!
As you can see, if I add a change event on react element, the change event can no longer bubble.
useEffect(() => {
containerRef.current.addEventListener("change", handleNativeChangeEvent);
}, [containerRef]);
If I add the change event through native javascript way(addEventListener), the change event can bubble normally.
But if I add the click event whatever through onClick synthesis event or addEventListener, the click event can always bubbles.
And why does the change synthesis event not bubble when the child are added through dangerouslySetInnerHTML
?
Why the change event have different bubbles behavior between clicking event?
I have looked into react source code and found out the reason.
Here is the key code
react/packages/react-dom/src/events/plugins/ChangeEventPlugin.js
Lines 293 to 305 in 9c8161b
The overall logic is like this.
- when the click event is triggered, the nearest React Node (targetNode) to the node that triggered the event is found
- determine if the targetNode is an
input
radio
orcheckbox
element, and if so, compare the values before and after to see if they have changed, and if so, derive the onChange event
But if the element that triggers the click event is rendered by dangerouslySetInnerHTML element, as in the example above, the latest React Node node div
will be found, then the shouldUseClickEvent(targetNode)
returns false, making it impossible to synthesize the onChange event.
@gaearon Is this a bug or is it intentional, if it is a bug I'm happy to raise a PR to fix it
This issue has been automatically marked as stale. If this issue is still affecting you, please leave any comment (for example, "bump"), and we'll keep it open. We are sorry that we haven't been able to prioritize it yet. If you have any new additional information, please include it with your comment!
Closing this issue after a prolonged period of inactivity. If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you!