-
Notifications
You must be signed in to change notification settings - Fork 47.2k
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 fix on input radio #11227
bug fix on input radio #11227
Conversation
// Update the wrapper around inputs *after* updating props. This has to | ||
// happen after `updateDOMProperties`. Otherwise HTML5 input validations | ||
// raise warnings and prevent the new value from being assigned. | ||
// Update the wrapper around inputs *after* updating props. |
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.
this comment isn't correct anymore since you've moved the updateDOMProperties
call below it. We would need to confirm that the original issue with validations firing doesn't occur. Can you write a dom fixture that demonstrates the issue and that it doesn't occur after this change?
@nhunzaker Any suggestions on how to write that, or what conditions triggered it?
So i'm not sure that the unit tests will catch this ( @nhunzaker might know) effectively give that it's a browser specific warning? I think we should move the original unit test in #7333 to a DOM fixture and ensure that it works. I think we also need understand why this was fixed inadvertantly in v16 before merging |
make radio's checked updated before the name
I tested https://jsfiddle.net/97gr5e65/1/ made by @aweary. After some debugging, I found an interesting point. Let me explain it with the test case I added. initial state: promising state after update: step1, update radio1: step2-1, update radio2's name: I think if we update checked first, it would be ok |
Hey everyone. Sorry! I was out of town and lost track. I'll start checking this out. |
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.
Tested in:
- IE9-11
- Safari Desktop 7.1, 8, 11
- Safari iOS 9
- Firefox 47, 56
- Chrome 42, 62
This checks out!
@jquense I made a test fixture to manually verify this: nhunzaker@f18c4c4
@landvibe Great work spotting this! Do you mind if I push this fixture to your PR?
Still, we need to figure out why restoreControlledState
isn't firing in this instance. Right now, I see that as the root of the problem.
Alternatively, could we just call updateNamedCousins
where this PR now has updateChecked
? Is there an advantage to one over the other?
// When a checked radio tries to change name, browser makes another radio's checked false. | ||
if (tag === 'input') { | ||
ReactDOMFiberInput.updateChecked(domElement, nextRawProps, 'radio'); | ||
} |
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'm trying to figure out why this is necessary (but it is definitely effective).
updateNamedCousins
in ReactDOMInput
should take care of this, but it looks like it doesn't run in the test case you've provided.
@jquense updateNamedCousins
gets called in restoreControlledState
, but for what ever reason it only fires on the button
, which I guess is clicked and responsible for the last trigger. The radio input never gets targeted by restoreControlledState
.
It feels like there's something deeper here that we need to fix.
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 think updateNamedCousins is called only on the button because of this code ReactTestUtils.Simulate.click(buttonNode);
I checked that updateNamedCousins is not called when I run your fixture.
DOMPropertyOperations.setValueForProperty( | ||
node, | ||
'checked', | ||
checked || false, |
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.
Kind of a bummer that we have to || false
here. It can't hurt, but I wonder if this is necessary (just with a quick test via https://codepen.io/nhunzaker/pen/qVadLo).
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 also think it's unnecessary.
@@ -669,6 +669,45 @@ describe('ReactDOMInput', () => { | |||
expect(cNode.checked).toBe(true); | |||
}); | |||
|
|||
it('should have correct checked value when radio names changed', () => { |
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.
Do you mind rephrasing this to should check the correct radio when the selected name moves?
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.
OK. yours is better
@nhunzaker new commit with your fixture |
targetType: ?string, | ||
) { | ||
var node = ((element: any): InputWithWrapperState); | ||
if (!targetType || targetType === node.type) { |
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.
In updateNamedCousins
, we check for radio buttons like:
function updateNamedCousins(rootNode, props) {
var name = props.name;
if (props.type === 'radio' && name != null) {
// ...
}
// ...
}
Can you use that check here? That would allow us to remove the targetType
argument and reading from the DOM.
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 added the code in updateProperties because updateWrapper also calls updateChecked
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.
Sorry for the delay. I had to spend some time figuring out what updateNamedCousins
is actually doing. It looks like this is necessary for controlled radios so that you can programmatically prevent them from changing via state (like not toggling state in a change handler).
This looks good, I'd just like for the conditions for applying updateChecked
to mirror that of updateNamedCousins
, which I've laid out in the comments.
@nhunzaker applied your comment |
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.
Looks good! I'm waiting on a build to do some final testing before merging. Thank you for sticking with me!
Verified in:
😅 (When am I finally going to automate this...) Thank you for sending this out. I apologize it took this long. This is a fantastic find! |
Fixed: #7630
The PR#7333 made this issue.
And now there is no validation warning that PR#7333 is mentioning.
I think React 16 resolved the validation warning issue, so I reverted it to the previous of PR#7333.
I also added a test case for #7630