-
Notifications
You must be signed in to change notification settings - Fork 47.4k
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
Use the virtual target for change events to avoid restoring controlled state on the real target #10444
Conversation
@@ -24,8 +48,14 @@ class SelectFixture extends React.Component { | |||
<option value="">Select a color</option> | |||
<option value="red">Red</option> | |||
<option value="blue">Blue</option> | |||
<option value="gree">Green</option> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🙈. I wonder who did this.
arg this is was beyond weird. yeah I originally had #10238 do this but ran it the issue you are seeing on the fixture select (#10238 (comment)) I am honestly not sure why it's happening. The value on the input ends up being empty by the time the onInput runs even tho it was correct for the Let me poke at it... |
Maybe the problem is we don't have corresponding setup calls in https://github.com/sebmarkbage/react/blob/2348742f0baccca745b2f76a2720706a56eafce1/src/renderers/dom/fiber/ReactDOMFiberComponent.js#L544 ? |
So one issue is that That's because |
With both events it only seems to break in the case where you change locations onChange. What I see is:
At no point though does the |
I think the issue that makes the behavior different in the nested case is that this returns the wrong thing and a change event gets fired on the surrounding "div". https://github.com/facebook/react/blob/master/src/renderers/dom/shared/eventPlugins/ChangeEventPlugin.js#L172 Because |
This ensures that they're consistent for the nested vs not case: 43e4619 However, this only works because the happen to ignore the restore event properly. The fact that this worked in the normal case seems super fragile to me. Is there another nesting where this breaks? So I'm not super happy with this solution. :/ |
I think I'm going to merge this because this solves this particular issue. I think we've discovered other issues here. If there is a change listener, higher up in the tree, then it will get invoked as a "change" event. I don't know what kind of consequences that will have. |
The failure repros only when two events are fired sequentially, where the second event is what updates the value.
Ensures that we use the same node to make decisions instead of two like we do now. This will cause restore to be called or not called consistently.
43e4619
to
7a513e3
Compare
ah that is tricky :/ is the underlying problem that the additional change event fires? I was seeing extractEvents called for the select first, then the div. The extractEvents shouldn't fire at all for the div right? |
f4392c7
to
1a480eb
Compare
If someone uses |
I think the It used to be that we sometimes would fall into the case where this was false for unknown targets. |
Hm. I'm going to change my patch a bit. I don't think we want to pass the virtual target as the event target in the event object. We don't do that elsewhere. With regard to when to fire this. I think we probably don't want to bubble the event on any blur which I think it what will happen now, right? |
We normally pass the native event target to the event object. This ensures that we do the same thing here. We still want to schedule a "restore" on the virtual target though since those are the only nodes known to React.
There's something off about the way we do bubbling and how we create custom events. We extract events once per subtree so that we can do the bubbling within that subtree. That means that we have to recreate the same event for each subtree. Ideally using the nativeEventTarget as the basis for all decisions so it's consistent. However, we can't do that right now because the change event plugin's I'm tempted to leave it semi-broken as is now so we don't break it more and then revisit semantics in 17. The workaround to get sane semantics is to use Portals for now. |
…ontrolled state on the real target (facebook#10444)" This reverts the meaningful (src, non-test) part of commit 3bc6432 since we've reverted the commit it depended on in 18083a8. I don't fully understand the negative implications of leaving this unreverted but it sounds like consensus is that it's safer to revert. I left the new fixture and verified it works correctly in Chrome 62 Mac, as well as the jest tests passing.
…ontrolled state on the real target (#10444)" (#10504) This reverts the meaningful (src, non-test) part of commit 3bc6432 since we've reverted the commit it depended on in 18083a8. I don't fully understand the negative implications of leaving this unreverted but it sounds like consensus is that it's safer to revert. I left the new fixture and verified it works correctly in Chrome 62 Mac, as well as the jest tests passing.
Fixes #10420
The problem is that we try to restore the controlled value after the
oninput
event. So we've restored it to its previous value by the time we fireonChange
. So the controlling component doesn't have a chance to update it.This ensures that we "restore controlled state" on the wrapper instead of the real target - which is a noop.