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

[RadioGroup] Warn for uncontrolled <-> controlled switch #14878

Merged
merged 10 commits into from
Mar 19, 2019

Conversation

manonthemat
Copy link
Contributor

@manonthemat manonthemat commented Mar 14, 2019

Closes #14696

@mui-pr-bot
Copy link

mui-pr-bot commented Mar 14, 2019

Details of bundle changes.

Comparing: bdb4baa...df1a893

bundle parsed diff gzip diff prev parsed current parsed prev gzip current gzip
@material-ui/core +0.01% 🔺 +0.01% 🔺 361,335 361,381 92,103 92,110
@material-ui/core/Paper 0.00% 0.00% 68,536 68,536 19,978 19,978
@material-ui/core/Paper.esm 0.00% 0.00% 61,725 61,725 18,888 18,888
@material-ui/core/Popper 0.00% 0.00% 30,458 30,458 10,567 10,567
@material-ui/core/styles/createMuiTheme 0.00% 0.00% 17,284 17,284 5,700 5,700
@material-ui/core/useMediaQuery 0.00% 0.00% 2,471 2,471 1,038 1,038
@material-ui/lab 0.00% 0.00% 170,524 170,524 49,897 49,897
@material-ui/styles 0.00% 0.00% 53,729 53,729 15,486 15,486
@material-ui/system 0.00% 0.00% 17,041 17,041 4,488 4,488
Button 0.00% 0.00% 90,262 90,262 26,730 26,730
Modal 0.00% 0.00% 88,646 88,646 26,317 26,317
colorManipulator 0.00% 0.00% 3,232 3,232 1,298 1,298
docs.landing 0.00% 0.00% 51,976 51,976 11,324 11,324
docs.main 0.00% 0.00% 651,342 651,342 202,307 202,307
packages/material-ui/build/umd/material-ui.production.min.js +0.01% 🔺 -0.00% 311,373 311,419 85,482 85,481

Generated by 🚫 dangerJS against df1a893

@joshwooding
Copy link
Member

joshwooding commented Mar 14, 2019

This approach won't work, the constructor is only called once and we need to check on prop changes. The check should probably be done in componentDidUpdate.

@joshwooding
Copy link
Member

Sorry, I wasn’t really clear. IsControlled is set in the constructor and doesn’t change you should do the same check in componentDidUpdate and warn if the result is different from isControlled.

@oliviertassinari
Copy link
Member

@manonthemat We have recently introduced uncontrolled behavior support for this component. We want to support it. What we are interestd into is to warn when people incorrectly switch between the uncontrolled and controlled mode.

@oliviertassinari oliviertassinari added PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI component: radio This is the name of the generic UI component, not the React module! labels Mar 14, 2019
@mbrookes
Copy link
Member

mbrookes commented Mar 14, 2019

Since we can't make the RadioGroup defaultValue a required prop, (since it isn't required when RadioGroup is controlled), I suggest we:

  1. Update the defaultValue description to something like:
  /**
-   * The default input value, useful when not controlling the component.
+   * The default input value of an uncontrolled RadioGroup. Required when `RadioGroup` is uncontrolled.
   */
  defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.bool]),
  1. Warn if RadioGroup is uncontrolled, and defaultValue is not provided.

  2. Optionally we could also warn if value or defaultValue is not valid, i.e. doesn't match the value of a child.

@manonthemat
Copy link
Contributor Author

Thanks for the guidance. I'll give it another shot.

@mbrookes
Copy link
Member

@manonthemat Hold fire on my suggestion. @oliviertassinari is suggesting (in private chat) that we shouldn't be opinionated. I personally disagree, but this isn't my personal project.

Let's reach a consensus on what to warn and what not before you devote more time to this PR.

@@ -96,7 +106,7 @@ RadioGroup.propTypes = {
*/
children: PropTypes.node,
/**
* The default input value, useful when not controlling the component.
* The required default input value of an uncontrolled RadioGroup.
Copy link
Member

@oliviertassinari oliviertassinari Mar 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • In 90% of the cases, users will be better off with a select radio value, no matter what.
  • NN/g encourages to always have a selected radio: https://www.nngroup.com/articles/checkboxes-vs-radio-buttons/.
  • But, it's not something everybody agrees with, e.g. Windows. They recognize that an always selected value should be the norm. However, there are exceptions where not providing a default value is more appropriate:

Exceptions: Don't have a default selection if:

  1. There is no acceptable default option for safety, security, or legal reasons and therefore the user must make an explicit choice. If the user doesn't make a selection, display an error message to force one.
  2. The user interface (UI) must reflect the current state and the option hasn't been set yet. A default value would - incorrectly imply that the user doesn't need to make a selection.
  3. The goal is to collect unbiased data. Default values would bias data collection.
  4. The group of radio buttons represents a property in a mixed state, which happens when displaying a property for multiple objects that don't have the same setting. Don't display an error message in this case since each object has a valid state.

So, I'm in favor of encouraging an always selected radio, but allow people to have zero selected: nothing required, but highly encouraged.

@@ -20,6 +20,16 @@ class RadioGroup extends React.Component {
}
}

componentDidUpdate(_prevProps, prevState) {
warning(
this.isControlled === (prevState === null),
Copy link
Member

@oliviertassinari oliviertassinari Mar 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something is off here, it makes me think we miss tests.

@oliviertassinari oliviertassinari added the new feature New feature or request label Mar 14, 2019
@oliviertassinari oliviertassinari self-assigned this Mar 15, 2019
@oliviertassinari oliviertassinari changed the title warning if RadioGroup is uncontrolled [RadioGroup] Warning uncontrolled <-> controlled switch Mar 15, 2019
@oliviertassinari oliviertassinari changed the title [RadioGroup] Warning uncontrolled <-> controlled switch [RadioGroup] Warn for uncontrolled <-> controlled switch Mar 15, 2019
@oliviertassinari oliviertassinari removed the PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI label Mar 15, 2019
Copy link
Member

@oliviertassinari oliviertassinari left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm proposing this alternative solution. But we should probably wait on #14585 before merging this one. It will avoid conflict, #14585 doesn't need one.

);
});

it('should warn when switching between uncontrolled to controlled', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: radio This is the name of the generic UI component, not the React module! new feature New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants