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

Vue Component's Boolean Prop default is false, not undefined. #11839

Closed
rockmandash opened this issue Aug 8, 2020 · 7 comments
Closed

Vue Component's Boolean Prop default is false, not undefined. #11839

rockmandash opened this issue Aug 8, 2020 · 7 comments
Assignees
Milestone

Comments

@rockmandash
Copy link

Vue Component has a special boolean prop use case, when not giving boolean prop default value, the boolean prop's default value is false, not undefined

Please see this minimum v6 example

TestProp.vue
<template>
  <div />
</template>

<script>
export default {
  props: {
    disabled: Boolean,
  },
  mounted() {
    console.log(this.disabled); // notice this line
  },
};
</script>
TestProp.stories.js
import TestProp from "./TestProp.vue";

export default {
  title: "TestProp",
  component: TestProp,
};

export const Primary = (args, { argTypes }) => {
  return {
    props: Object.keys(argTypes),
    components: { TestProp },
    template: "<TestProp />", // this will log out `false`
    template: '<TestProp v-bind="$props" />', // this will log out `undefined`
  };
};

If Storybook not changing default boolean prop to false, people will often trigger this warning when tweaking knobs.

Warning: A component is changing an uncontrolled input of type checkbox to be controlled. Input elements should not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://fb.me/react-controlled-components

Then people will have to write Primary.args = { disabled: false } manually to suppress this warning.

@shilman shilman added this to the 6.1 args milestone Aug 9, 2020
@deviprsd
Copy link

It's just not vue, the default for BooleanControl should be false unless provided in the args.

Stacktrace
Warning: A component is changing an uncontrolled input of type checkbox to be controlled. Input elements should 
not switch from uncontrolled to controlled (or vice versa). Decide between using a controlled or uncontrolled input
 element for the lifetime of the component. More info: https://fb.me/react-controlled-components
    in input (created by BooleanControl)
    in label (created by Context.Consumer)
    in Styled(label) (created by BooleanControl)
    in BooleanControl (created by ArgControl)
    in ArgControl (created by ArgRow)
    in td (created by ArgRow)
    in tr (created by ArgRow)
    in ArgRow (created by ArgsTable)
    in tbody (created by ArgsTable)
    in table (created by Context.Consumer)
    in Styled(table) (created by ArgsTable)
    in div (created by Context.Consumer)
    in Styled(div) (created by ArgsTable)
    in ArgsTable (created by ControlsPanel)
    in ControlsPanel
    in div (created by AddonPanel)
    in AddonPanel
    in div (created by Context.Consumer)
    in Styled(div)
    in div (created by Context.Consumer)
    in Styled(div)
    in Unknown
    in Unknown
    in Unknown
    in Unknown (created by ManagerConsumer)
    in ManagerConsumer (created by Panel)
    in Panel (created by Layout)
    in div (created by Context.Consumer)
    in Styled(div) (created by Panel)
    in Panel (created by Layout)
    in div (created by Context.Consumer)
    in Styled(div) (created by Main)
    in div (created by Context.Consumer)
    in Styled(div) (created by Main)
    in Main (created by Layout)
    in Layout (created by Context.Consumer)
    in WithTheme(Layout)
    in Unknown
    in div (created by Context.Consumer)
    in Styled(div)
    in Unknown (created by SizeMeRenderer(Component))
    in SizeMeReferenceWrapper (created by SizeMeRenderer(Component))
    in SizeMeRenderer(Component) (created by SizeMe(Component))
    in SizeMe(Component)
    in ThemeProvider
    in Unknown (created by ManagerConsumer)
    in ManagerConsumer (created by Manager)
    in EffectOnMount (created by Manager)
    in Manager (created by Context.Consumer)
    in Location (created by QueryLocation)
    in QueryLocation (created by Root)
    in LocationProvider (created by Root)
    in HelmetProvider (created by Root)
    in Root

@backbone87
Copy link
Contributor

backbone87 commented Aug 31, 2020

Just some thoughts after talking to @shilman about this:
This isnt a Vue specific problem. The warning comes from React and probably relates to how storybook initializes a checkbox value (wild guess on my side).

Regarding your Vue example:
Having disabled be undefined is perfectly legal according to your prop definition. You want to declare your prop the following way props: { disabled: { type: Boolean, default: false } }, which makes sure that if the prop is not passed or undefined is passed, will result in false being assigned. This may be inconsistent behavior on Vue's side, but has nothing to do with storybook. The boolean handling of Vue has only 3 cases:

  • Not passed -> false
  • Empty string passed -> true
  • String passed which matches the prop name when hypenated -> true

Everything else is left untouched, including when undefined is passed.

@shilman
Copy link
Member

shilman commented Aug 31, 2020

Whoopee!! I just released https://github.com/storybookjs/storybook/releases/tag/v6.0.21 containing PR #12322 that references this issue. Upgrade today to try it out!

Closing this issue. Please re-open if you think there's still more to do.

@shilman shilman closed this as completed Aug 31, 2020
@sebastienbarre
Copy link

sebastienbarre commented Feb 15, 2021

Unfortunately this issue also exists as of today, version 6.1.18, for numbers specifically.

Given this React component prop types for example:

Hours.propTypes = {
  /**
   * Amount of hours?
   */
  hours: PropTypes.number,
};

Hours.defaultProps = {
  hours: 0,
};

The controls add-ons will display:

image

and you will get the exact same warning as soon as you enter a value in the input field that says "Adjust number dynamically", for the same reason I assume (it was undefined in Storybook's React component, now defined):

react-dom.development.js:67 Warning: A component is changing an uncontrolled input to be controlled. 
This is likely caused by the value changing from undefined to a defined value, which should not happen. 
Decide between using a controlled or uncontrolled input element for the lifetime of the component

Should we re-open?
Thanks

@shilman
Copy link
Member

shilman commented Feb 15, 2021

@sebastienbarre Might be fixed in an open PR by @tmeasday

@tmeasday
Copy link
Member

Here's the PR: #13911

@sebastienbarre
Copy link

Thanks @tmeasday, looking forward the next release. I tried the pre-release, it broke my Storybook pretty badly. I'm sure it will be all good in the official release.

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

6 participants